PROFIL / INDEX© Clément Depernet / 2026

← Retour à la liste

18 août 20263 min de lecture

Anatomie du CTF caché dans ce site

Ce portfolio contient un challenge à trois étapes dont toutes les réponses sont déjà dans ton navigateur. C'est volontaire — et c'est une démonstration de la faille que je cherche le plus souvent en audit : la confiance placée dans le client.

intermediate#ctf#web#appsec#meta

Ouvre la console de ce site avec Ctrl+K et tape help. Tu trouveras un CTF à trois étapes. Ce write-up n’en donne pas les flags — il explique pourquoi il est construit exactement comme il l’est, et ce que sa conception raconte sur la sécurité web.

Le principe : tout est côté client

Il n’y a pas de serveur dans ce challenge. Le site est statique, servi en fichiers plats derrière Caddy. La vérification des flags se fait dans ton navigateur, en JavaScript, contre des empreintes SHA-256 livrées dans le bundle.

C’est, littéralement, l’anti-pattern que je signale le plus souvent en test d’intrusion : un contrôle de sécurité exécuté là où l’attaquant a tous les droits. Ici c’est assumé et pédagogique. En production, c’est une faille.

Étape 1 — la reconnaissance ne coûte rien

La première étape ne se résout pas dans la console : le flag est ailleurs, dans un fichier que tous les crawlers lisent et que presque personne n’ouvre à la main. Le réflexe qu’elle récompense — regarder ce que le serveur offre gratuitement avant de chercher compliqué — est le premier geste de tout audit.

Disallow: dans un robots.txt n’a jamais protégé quoi que ce soit. C’est une consigne polie adressée aux robots bien élevés, pas un contrôle d’accès. Le lister, c’est parfois pointer un projecteur sur exactement ce qu’on voulait cacher.

Étape 2 — encoder n’est pas chiffrer

La deuxième étape empile deux transformations réversibles sans clé : de l’hexadécimal et un ROT13. Aucune des deux n’est du chiffrement. C’est une confusion que je vois régulièrement dans du vrai code : un jeton « obscurci » en base64 traité comme s’il était secret.

Règle simple : s’il n’y a pas de clé, ce n’est pas du chiffrement. base64, hex, ROT13, URL-encoding — ce sont des encodages. Reversibles par quiconque, par définition. Un secret protégé par un encodage n’est pas protégé.

Étape 3 — la démonstration se retourne sur elle-même

La dernière étape est un XOR à clé répétée, et la clé est écrite en clair sur la page. Une fois le flag obtenu, l’énoncé pose la vraie question : pourquoi as-tu pu résoudre ce CTF entier sans jamais parler au serveur ?

Parce que le SHA-256 de chaque flag est dans le code que ton navigateur a téléchargé. Un attaquant motivé n’a même pas besoin de résoudre les énigmes : il peut extraire les empreintes et les attaquer hors-ligne, ou lire directement les charges utiles dans les sources. Le challenge est « sécurisé » uniquement par la bonne volonté du joueur.

La leçon, transposée en production

Remplace « flag » par « prix d’un article », « rôle utilisateur » ou « solde de compte », et tu obtiens des bugs que j’exploite régulièrement :

  • un montant de paiement calculé côté client et fait confiance côté serveur ;
  • un isAdmin: false dans un JWT non signé, modifiable à volonté ;
  • une validation de formulaire uniquement en JavaScript, contournée avec un simple curl.

Le principe est invariant : le client est un territoire hostile. Tout ce qui compte doit être vérifié côté serveur, sur des données que le client ne contrôle pas. Ce CTF est la version jouable de cette phrase.

Si le raisonnement t’a plu, l’étape 3 te dit comment me le faire savoir.

SEC / OPS / CD-01

Astro + Tailwind, conteneurisé, servi derrière Caddy · Source · Thème sonore : Severance (Theodore Shapiro)

PRÊT / CD-01