[LeHack] - Poor
Sommaire
LeHack2025 - Cet article fait partie d'une série.
Description #
La cible de ce challenge est l’application web POOR (Proof of Overwhelming Richness) se trouvant à l’url https://poor.wargame.rocks
.
L’application semble permettre de gérer des portefeuilles Bitcoin personnalisés via l’utilisation d’informations utilisateur, comme le montre sa page d’accueil :
Utilisation de l’application #
Pour utiliser l’application il est nécessaire d’obtenir un token d’un utilisateur valide puis d’intéragir avec l’API mise en place.
Pour récupérer un token, un exemple est disponible sur la page d’accueil via un utilisateur de test :
curl --request POST --url https://poor.wargame.rocks/cognito-proxy/oauth2/token --data grant_type=client_credentials --data client_id=1qconf4f2v146v0qi6kjn25l3m --data client_secret=ni1e9k9a25vp5eq2karankjn6atroof1r354s7havetpjunkj2d
Une fois le token récupéré, voici la structure de la commande qui permet d’intéragir avec l’API :
curl --request GET --url https://poor.wargame.rocks/[endpoint_api] --header 'Authorization: Bearer [TOKEN]' --header 'X-Env: dev'
La documentation de l’API décrit tous les endpoints disponibles :
Un endpoint va particulièrement nous intéresser ici : /api/admin/bitcoin
permettant de récupérer l’objet Bitcoin de l’utilisateur dont on a fourni le token.
L’objet Bitcoin ne dispose que d’un attribut key
étant une chaîne de caractère.
L’attribut key stocke très certainement le flag
En envoyant une requête Burp (correspondant à la requête curl en CLI) sur l’endpoint /api/admin/bitcoin
, on obtient bien la valuer de l’attribut key
de l’objet Bitcoin de l’utilisateur de test (ici “–demo–”) et un message nous indiquant que la même requête sur l’environnement de prod nous donnerait accès à la master key (correspondant certainement au flag).
Notre but est assez clair désormais : récupérer l’objet Bitcoin de l’utilisateur test sur l’environnement de production
Blocage de l’environnement #
L’utilisation de la commande pour récupérer un token avec l’utilisateur test permet d’obtenir un JWT :
Ce JWT comporte plusieurs champs dont 2 intéressants :
- Le scope : il décrit l’environnement dans lequel ce JWT est valide et les droits que donne ce JWT. Ici, le JWT de l’utilisateur de test donne tous les droits mais dans l’environnement env/dev uniquement.
- L’issuer ou l’émetteur (iss) : il décrit qui a émis le token, ici un proxy cognito hébergé sur une instance AWS.
echo [JWT] | base64 -d
Si on essaie de changer directement l’entête X-Env
dans la requête à l’endpoint /api/admin/bitcoin
, on obtient un message d’erreur :
Une vérification de l’API est donc bien réalisé sur le token émis : si le token est émis pour un environnement donné (ici env) alors il n’est pas possible de le modifier ultérieuement.
La vulnérabilité ne se situe donc pas au niveau de la vérification du scope par l’API, mais certainement au niveau de l’attribution du scope par l’issuer.
Changement d’environnement #
En tentant de modifier directement le scope depuis la commande de génération de token via l’ajout de la donnée --data scope='YoloSwag'
:
curl --request POST --url https://poor.wargame.rocks/cognito-proxy/oauth2/token --data grant_type=client_credentials --data client_id=1qconf4f2v146v0qi6kjn25l3m --data client_secret=ni1e9k9a25vp5eq2karankjn6atroof1r354s7havetpjunkj2d --data scope='YoploSwag'
On obtient le message d’erreur suivant :
{"error":"Should not happens, empty scope ? really ?!?"}
Un indice donné par le concepteur de l’épreuve pour nous indiquer que nous sommes sur la bonne voie.
En changeant le scope par la valeur “env/prod”, on obtient un JWT qui ne précise plus le scope “env/dev” :
Celui-ci est adonc accepté dans l’environnement de production et nous permet d’obtenir le flag :
🚩 Flag : leHACK{n0lI73_73_84S74Rd3s_c4R80RunD0RuM}