Solution to Challenge 1: Poison [1/2]

Author

Le magicien quantique

Published

May 12, 2024

import numpy as np
import requests as rq

from fl.model import NN
from fl.preprocessing import load_mnist, data_to_client
from fl.federated_learning import train_and_test


URL = "http://localhost:8000/"
# URL = "https://du-poison.challenges.404ctf.fr/" 

We start by retrieving the common model:

dataset = load_mnist()
model = NN()
model.load_weights("../weights/base_fl.weights.h5")
weights = model.get_weights()

Our goal is to poison the common model. To do this, we don’t need to train the model; we only use it to retrieve the sizes of the weight matrices. Within the framework of federated learning, we can do whatever we want on our side as long as we return weights of the correct size. For example, we can return random weights:

d = {
    "w1": np.random.random(weights[0].shape).tolist(),
    "b1": np.random.random(weights[1].shape).tolist(),
    "w2": np.random.random(weights[2].shape).tolist(),
    "b2": np.random.random(weights[3].shape).tolist(),
    "w3": np.random.random(weights[4].shape).tolist(),
    "b3": np.random.random(weights[5].shape).tolist(),
    "w4": np.random.random(weights[6].shape).tolist(),
    "b4": np.random.random(weights[7].shape).tolist()
}
rq.get(URL + "healthcheck").json()
{'message': 'Statut : en pleine forme !'}
rq.post(URL + "challenges/1", json=d).json()
{'message': 'Bravo ! Voici le drapeau : 404CTF{0h___dU_P01sON} (score : 0.1095)'}