Retour

BYUCTF 2025 – JWTF

A CTF hosted by BYU Cyberia, the official CTF team of Brigham Young University.

JWTF | catégorie | Web

Ce challenge portait sur la manipulation de JWT (JSON Web Tokens) dans une application Flask. Le serveur utilisait une JWT Revocation List (JRL) pour bloquer les tokens admin compromis. Le but était clair : obtenir un token admin valide mais pas révoqué.

Étape 1 – Analyse du code source

Une fois les sources examinées, on découvre la présence d’une JRL avec vérification simple :

if session in jrl: return redirect('/')

C’est ici que réside la faille. Le serveur compare les JWT **en tant que chaînes**, sans les décoder !

Étape 2 – Récupération du JWT bloqué

curl https://jwtf.chal.cyberjousting.com/jrl

On obtient un JWT complet : header, payload et signature. Le payload contient bien : {"admin": true, "uid": "1337"}

Étape 3 – Bypass par encodage modifié

En modifiant légèrement le payload (ex : ajout d’un \), le JWT reste valide côté déchiffrement, mais diffère au niveau chaîne, donc il contourne la JRL :

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJhZG1pbiI6dHJ1ZSwidWlkIjoiMTMzNyJ9\.
BnBYDobZVspWbxu4jL3cTfri_lxN0i33q-TRLbHV-ew
  
Plus qu'à bypass JWT dans Burp Suite

Étape 4 – Récupération du Flag

Le cookie JWT forgé est injecté via Burp dans une requête GET /flag. Résultat :

byuctf{did_if_this_means_anything_but_maybe_its_useful_somewhere_97ba5a70d94d}
Réponse du flag dans Burp

Conclusion

Cette faille repose sur une mauvaise vérification de la révocation JWT par comparaison de chaînes. Il aurait fallu comparer les **claims déchiffrés** ou utiliser un identifiant unique (JTI) pour chaque token.

Cooking Flash | catégorie | Web

Objectif

Exploiter une injection SQL dans un champ GET du site cooking.chal.cyberjousting.com afin d'exfiltrer le flag en base de données. Le site ressemble à ça :

step

🔍 Analyse initiale

On commence par explorer les paramètres en observant les requêtes envoyées via Burp Suite à l'aide de PayloadsAllTheThings . On repère que le champ tags dans la requête GET est injectable :

Analyse de la requête Burp

Test de l'injection

On injecte un ' dans le paramètre tags ce qui déclenche une erreur de type OperationalError SQLite, preuve d’une mauvaise gestion des entrées utilisateurs :

step

Extraction des données

On injecte ensuite une requête UNION SELECT avec des valeurs explicites, puis des colonnes comme username et password provenant de la table user.

step

Cela nous retourne 400 Bad Request car il faut qu'on encode à présent notre url !

step

Conclusion

Challenge réussi ! La vulnérabilité SQLi était présente sur un paramètre GET sans filtrage, permettant d’extraire le flag après validation du nombre de colonnes et de la table cible. Un bon cas pratique pour tester l'automatisation (Burp) et l'analyse manuelle.

Flag : byuctf{pl34s3_p4r4m3t3r1z3_y0ur_1nputs_4nd_h4sh_y0ur_p4ssw0rds}

step

Willy Wonka Web | CVE-2023-25690

🔍 Étape 1 : Analyse des fichiers Apache

En inspectant les configurations Apache, on découvre l’utilisation de mod_proxy et mod_rewrite avec un reverse proxy sur /name/ :

LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
VirtualHost *:80
    ServerName localhost
    DocumentRoot /usr/local/apache2/htdocs

    RewriteEngine on
    RewriteRule "^/name/(.*)" "http://backend:3000/?name=$1" [P]
    ProxyPassReverse "/name/" "http://backend:3000/"

    RequestHeader unset A
    RequestHeader unset a
VirtualHost
      

Cette configuration mal sécurisée permet potentiellement une injection de requêtes HTTP via CRLF (%0d%0a).

Étape 2 : Compréhension et utilisation de la CVE-2023-25690

Cette faille permet d'injecter des en-têtes HTTP en abusant d’une mauvaise réécriture via RewriteRule et un manque de nettoyage des requêtes. Un script PHP caché traite un paramètre secret :

?php

if(isset($_GET['id'])){
    $id = $_GET['id'];
    echo 'You category ID is: ' . $id;
}else{
    echo "Please insert the ID parameter in the URL";
}

#Internal secret functionality
if(isset($_GET['secret'])){
    $secret = $_GET['secret'];

    shell_exec('nslookup ' . $secret);
}
?>

Il est possible d'injecter une requête nslookup à travers ce script.

Étape 3 : Test d’URL vulnérable

Nous testons l’injection via un paramètre mal filtré :

/name/test%20HTTP/1.1%0d%0aHost:%20wonka.chal.cyberjousting.com%0d%0a%0d%0aGET%20/name/test Injection URL testée dans le navigateur

Le serveur répond avec It works!, preuve que la requête a été traitée par un second backend.

Étape 4 : Récupération du flag via Burp Suite

En modifiant la requête GET dans Burp Repeater avec la payload ci-dessus, cela permet d’exfiltrer le flag :

Burp Suite - DNS trigger
Haut de page