LIFWEB TP CTF - Capture the Flag

Un serveur réalisé en Node.js avec le framework https://hapi.dev/ est déployé sur https://lifweb.univ-lyon1.fr/.

Principe

Ce serveur de type Capture The Flag (CTF) propose des défis de difficultés croissantes, tous sur le même format :

  • On interroge la route de départ en GET.
  • La réponse JSON contient un attribut href avec une URL sur laquelle envoyer une requête POST pour déclencher le défi.
  • La réponse à cette requête contient des challenges et une route sur laquelle les vérifier.
  • Il faut renvoyer les challenges un-à-un sur la route donnée.
  • À leur tour la vérification des challenges peut déclencher d’autres challenges ou valider le challenge.

Niveaux

Les niveaux de difficultés sont les suivants :

  1. 🍰 Renvoyer le challenge en temps interactif. On peut le faire à la main, par exemple avec https://httpie.io/ ou https://curl.se/.
  2. 🧀 Renvoyer le challenge en temps limité. Ici, il faut automatiser, car on n’a que quelques dizaines de millisecondes pour répondre.
  3. 🧂 Renvoyer une succession de challenges consécutivement. Un challenge en déclenche en nouveau, il y en a trois successifs.
  4. 🌶️ Renvoyer plusieurs challenges en parallèle. On ne peut valider les challenges qu’un par un, mais il y en a quatre à valider en temps limité.

Notons que les niveaux peuvent échouer à cause de la concurrence d’accès ou des latences. Il faut parfois réessayer quelques fois pour déclencher le succès, voire changer de réseau pour diminuer la latence.

Utilisation de l’API

L’API est accessible sur https://lifweb.univ-lyon1.fr/documentation.

Une clef d’API au format UUIDv4 (Wikipédia) est fournie dans Tomuss. La clef sert à s’authentifier sur le serveur, il faut la transmettre dans l’en-tête X-API-KEY avec fetch. Par exemple, pour voir la liste des challenges déjà validés :

fetch("https://lifweb.univ-lyon1.fr/users", {
  method: "GET",
  headers: {
    "Content-Type": "application/json",
    "X-API-KEY": "099f1cd0-23a2-4cef-82a3-769fe9ceb2e2",
  },
});

L’équivalent avec https://httpie.io/ et avec https://curl.se/

http https://lifweb.univ-lyon1.fr/users X-API-KEY:099f1cd0-23a2-4cef-82a3-769fe9ceb2e2
curl --header "Content-Type: application/json" --header "X-API-KEY: 099f1cd0-23a2-4cef-82a3-769fe9ceb2e2" --request GET https://lifweb.univ-lyon1.fr/users

Exemple d’utilisation

Pour déclencher le niveau 1 on utilisera (avec httpie)

http POST https://lifweb.univ-lyon1.fr/level/1/start X-API-KEY:${XAPIKEY}

On recevra une réponse JSON semblable à la suivante :

{
  "challenges": ["4481d8bdb442fceefeaed9b1d40ee872"],
  "expires_at": "2024-02-19T17:22:12.506Z",
  "generated_at": "2024-02-19T17:19:12.506Z",
  "href": "https://lifweb.univ-lyon1.fr/level/1/check/1"
}

Il faut récupérer la valeur du challenge et la poster sur la route href comme suit :

http POST https://lifweb.univ-lyon1.fr/level/1/check/1 X-API-KEY:${XAPIKEY} challenge=${CHALLENGE}

On reçoit alors un succès semblable au suivant, ici à la main en environ 40s :

{
  "duration_ms": 40583,
  "id_lvl": 1,
  "success": {
    "challenge": true,
    "level": true,
    "stage": true
  }
}

Évaluation

⚠️ L’état des succès sera relevé le 2024-04-01 23:59 et participera à l’évaluation de l’UE. ⚠️

Techniquement, on peut réaliser les défis dans n’importe quel langage de programmation. Ici, on imagine le faire en JavaScript en Node.js ou dans le navigateur, mais tous les moyens sont bons. Ce peut être plus ou moins facile selon le langage. Amusez-vous ! 🥳