HeatKeeb
Description
CTF: STACK the Flags 2022
Jaga had gained interest in custom keyboards and has created a platform to create your own keebs! We know we created his custom keeb on the 22nd of September 2022, at 09:41:17 SGT. Oddly specific but we know it’s true.
misc_heatkeeb.zip
Solution
Pwned by @skytect and @fishjojo1
Let’s open up the webpage.

It seems that we need a token. Let’s check out the source code.
# app.py L98–L135@app.post("/build")def build(    request: Request,    name: str = Form(...),    frameColor: str = Form(...),    keyColor: str = Form(...),    textColor: str = Form(...),    specialColor: str = Form(...),):    t = datetime.datetime.now(pytz.timezone("Asia/Singapore"))    seed = int(t.timestamp())    random.seed(seed)    token = "".join(        random.choices(            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", k=16        )    )    with shelve.open("keebdb") as db:        db[token] = {            "name": name,            "frameColor": hex_to_rgb(frameColor),            "keyColor": hex_to_rgb(keyColor),            "textColor": hex_to_rgb(textColor),            "specialColor": hex_to_rgb(specialColor),            "text": "default",        }    img = draw_keeb(        name,        hex_to_rgb(frameColor),        hex_to_rgb(keyColor),        hex_to_rgb(textColor),        hex_to_rgb(specialColor),    )    img.save(f"keebs/keeb-{token}.png")    request.session["token"] = token    return templates.TemplateResponse(        "build.html", {"request": request, "resp": "Success!", "token": token}    )The seed is based on the time :0 Let’s try to generate the seed based on the time given in the description.
import datetimeimport pytzimport random
t = datetime.datetime(2022, 9, 22, 9, 41, 17, 0)seed = int(t.timestamp())random.seed(seed)token = "".join(    random.choices(        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", k=16    ))print(token)  # rMwwbpMkzAwyRoWsUsing the seed, we can access Jaga’s keeb!

Let’s go back to the code to find where the flag is.
# app.py L237–L251@app.post("/text")def flag(request: Request, text: str = Form(...)):    if "token" in request.session:        with shelve.open("keebdb") as db:            token = request.session["token"]            if token in db:                if token == ADMIN_TOKEN and text.upper() == KEY:                    return templates.TemplateResponse(                        "flag.html", {"request": request, "word": text, "flag": FLAG}                    )                elif text.upper() == db[token]["text"]:                    return templates.TemplateResponse(                        "flag.html", {"request": request, "word": text}                    )    return templates.TemplateResponse("flag.html", {"request": request})It seems that we need to key the matching word in the following text field somehow.

If we explore further around the GUI, we find that we can generate a heatmap of the word.

Looking at our keyboard, the hotspots appear to make out the letters asertghnil. Let’s try to unscrable the letters.

When we key in earthlings to check the latest favourite word, we get the flag!
STF22{h34t_k3yb04rD}