Le 25/10/2023 j’ai pu participer au MetaRed CTF 2023 avec mon équipe Pand’hack. Je vais vous présenter le challenge que j’ai pu résoudre dans la catégorie Web.
Description du challenge
Espérons que le challmaker ne nous mens pas sur la difficulté du challenge et qu’il est réellement possible d’avoir le flag avec seulement deux requêtes. 🤓
Analyse
Lorsque je me rends sur le lien fourni, j’ai directement l’erreur suivante :
1
{"error":"Missing JWT token"}
Heureusement, nous avons accès au code source pour avoir plus d’informations sur le fonctionnement du site web :
from flask import Flask, request, jsonify, make_response from flask_limiter import Limiter from jwt import decode, encode, exceptions import random from random import randint import os from flask import Flask from flask_limiter import Limiter from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter( app=app, default_limits=["2 per minute"], key_func=get_remote_address, )
On remarque rapidement que pour avoir le flag, il faut que le payload du jwt contienne un champ user avec la valeur admin.
1 2
if user.lower() == 'admin': return jsonify({"flag": FLAG}), 200
Mais le principe du JWT est que le payload et le header sont signés avec une clé secrète. Cela signifie que si je modifie le payload, la signature ne sera plus valide et le serveur refusera le token.
Le JWT est signé avec app.secret_key qui est la résultante du préfixe “Sup3S4f3” suivi d’un nombre aléatoire entre 0 et 1 000 000 000 000. Par exemple, elle pourrait ressembler à Sup3S4f3123456789, ce qui nous facilite la tâche pour la brute force.
Exploit
Récupération d’un jwt
Dans un premier temps, vu que je n’ai pas encore de jwt, je vais devoir en demander un au serveur. Pour cela, je vais utiliser le script suivant :
1 2 3 4 5 6 7 8 9 10 11
import requests
base_url = "https://jwt.ctf.cert.unlp.edu.ar/"
response = requests.get(base_url)
if'WWW-Authenticate'in response.headers: jwt_token = response.headers['WWW-Authenticate'].split('Bearer ')[1] print("JWT pour un utilisateur non privilégié:", jwt_token) else: print("Le JWT n'a pas été trouvé dans la réponse.")
voici l’output du script :
1
JWT pour un utilisateur non privilégié: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoibm9uIHByaXZpbGVnZWQifQ.dNxWC7BTKLZqKoqDd-XCWE2MOC7lElrRVdJpbLSxR4M