Browse CTFs New CTF Sign in

IDOR (UUID guessable)

web_auth_sessions Difficulty 1–5 30 min certifiable

Theory

Why This Matters

The widespread adoption of UUIDs as object identifiers was partly motivated by the belief that their 128-bit space made enumeration attacks impractical compared to sequential integers. However, this belief is only valid for UUID v4 (randomly generated). UUID v1, which encodes the generating host's MAC address, a clock sequence, and a 100-nanosecond timestamp, is predictable once an attacker obtains even a single UUID from the target system. In 2019, researchers demonstrated that UUID v1 IDs generated by popular Node.js and Java libraries could be predicted within a narrow time window, enabling targeted resource enumeration. More commonly, even cryptographically strong UUIDs are rendered insecure by application-level leakage: UUIDs appear in password-reset links, email notifications, API responses for related objects, and access logs — effectively reducing the entropy the attacker must overcome.

Core Concept

UUID (Universally Unique Identifier) is a 128-bit value standardized in RFC 4122 with five versions. The security-relevant distinction is between version 1 and version 4.

UUID v1 structure encodes: a 60-bit timestamp (100-nanosecond intervals since 15 October 1582), a 14-bit clock sequence (to handle clock adjustments), and a 48-bit node field (typically the MAC address of the generating host, or a random value if the MAC is unavailable). Because the timestamp dominates the structure, two UUIDs generated close in time will differ only in their timestamp field. An attacker who obtains one UUID from a target system at a known time can reconstruct the approximate generation timestamp and enumerate nearby UUIDs by varying the timestamp bits within a plausible window.

UUID v1 format (hex groups separated by hyphens): time_low-time_mid-time_hi_and_version-clock_seq-node. The version nibble is 1 in bits 12–15 of the third group.

UUID v4 fills all bits with cryptographically random values (except two version bits). With 122 bits of randomness, brute-force enumeration is computationally infeasible — but only if the UUID is not leaked through other channels.

UUID leakage vectors include: password-reset URLs sent to the target user (if intercepted), webhook confirmation emails, Referer headers when the UUID appears in a URL that the browser follows to an external resource, API responses for related objects (e.g., a shared document response that includes the creator's profile UUID), and server-side logging endpoints left accessible.

Technical Deep-Dive

import uuid, time, struct

# Inspect a UUID v1 and extract its timestamp
sample = uuid.UUID("1ec5d372-4b3a-11ee-be56-0242ac120002")
print(f"Version: {sample.version}")          # 1
print(f"Variant: {sample.variant}")
# UUID v1 timestamp = 100-ns intervals since 1582-10-15
UUID_EPOCH_DELTA = 0x01b21dd213814000        # offset to Unix epoch
ts_100ns = sample.time                        # raw UUID v1 timestamp
unix_ts = (ts_100ns - UUID_EPOCH_DELTA) / 1e7 # convert to Unix seconds
print(f"Generated at: {time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(unix_ts))}")
print(f"Node (MAC or random): {sample.node:#014x}")

# Generate candidate UUIDs within a 1-second window around the known timestamp
# An attacker knows the target account was created at approximately unix_ts
candidates = []
for delta_100ns in range(-10_000_000, 10_000_000, 100):  # ±1 second, 100ns steps
    new_ts = ts_100ns + delta_100ns
    # Reconstruct UUID v1 fields
    time_low  = new_ts & 0xFFFFFFFF
    time_mid  = (new_ts >> 32) & 0xFFFF
    time_hi   = (new_ts >> 48) & 0x0FFF | 0x1000   # version = 1
    clock_seq = sample.clock_seq                     # same clock_seq assumed
    node      = sample.node
    candidate = uuid.UUID(fields=(time_low, time_mid, time_hi, clock_seq >> 8,
                                   clock_seq & 0xFF, node))
    candidates.append(str(candidate))

print(f"Generated {len(candidates)} candidates to probe")
# Feed candidates into Burp Intruder or httpx for parallel probing
# Extract all UUIDs from an application's responses using Burp Suite logger
# Grep pattern for UUID v1 detection (version nibble = 1 in third group):
grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}' burp_log.txt

Security Assessment Methodology

  1. Collect observed UUIDs — interact with the application, capturing all UUIDs that appear in API responses, URLs, emails, and HTTP headers. Use Burp Suite's Logger++ to extract UUIDs with a regex filter.
  2. Classify UUID version — inspect the third hyphen-group: a 1 in the 13th character indicates v1; a 4 indicates v4. UUID v1 is the primary target for prediction; UUID v4 targets focus on leakage.
  3. Extract UUID v1 timestamp and node — use the Python uuid library to decode the sample UUID's generation time and node field.
  4. Generate candidates — write a prediction script (as above) covering a plausible generation window (±60 seconds for account creation, ±5 seconds for short-lived resources).
  5. Probe candidates at scale — feed the candidate list into Burp Intruder (Sniper mode, payload list) or httpx to test each UUID against the target endpoint. Filter 200 responses.
  6. For UUID v4, hunt for leakage — check password-reset flows, invitation links, email footers, and Referer headers for UUID exposure. If a UUID leaks, use it directly without prediction.
  7. Verify with two-account testing — confirm that a leaked or predicted UUID belonging to Account B is accessible when authenticated as Account A.

Defensive Countermeasure — Use UUID v4 (or ULID with cryptographic randomness) exclusively for all externally exposed object identifiers. Audit all application flows that transmit UUIDs to confirm they do not appear in Referer headers, email bodies accessible to third parties, or unauthenticated API responses. Log access attempts and alert on unusual enumeration patterns (high volume of 404s from a single IP against UUID-shaped paths).

Common Assessment Errors

  • Assuming all UUIDs are equally random — the version digit distinguishes predictable v1 from random v4; always decode a sample before concluding that UUIDs are safe.
  • Missing UUID leakage in email flows — password-reset and invitation emails that include a UUID in the URL are the most common source of targeted UUID theft; test these flows explicitly.
  • Generating too narrow a prediction window — server clock drift, load-balancer forwarding delays, and queued processing can shift the actual UUID generation time by several seconds from the observed request time; use at least ±60 seconds.
  • Not checking the node field — if the node field is not the MAC address but a random value, it resets on process restart, meaning UUIDs generated in different server instances have different node values and candidate sets must account for this.
  • Ignoring Referer header leakage — a page at https://victim.com/docs/<uuid> that loads a third-party script will send the UUID in the Referer header to the third-party origin; check JS bundle analytics, fonts, and CDN references.
  • Treating UUID v4 as unhackable — 122 bits of randomness is infeasible to brute-force, but a UUID that appears in only one additional place (a 404 error page, a debug header) is no longer secret.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0007 Knowledge of authentication, authorization, and access control methods Covers identifier-based access control and why UUID version and leakage behaviour determine real-world exploitability
K0065 Knowledge of policy-based and attribute-based access control Reinforces that cryptographic identifier strength is a component of access policy, not a substitute for server-side ownership checks
S0001 Skill in conducting vulnerability scans and recognizing vulnerabilities in security systems Practises UUID version classification, timestamp extraction, candidate generation, and Burp-based probing
T0028 Task: Identify systemic security issues based on vulnerability and configuration data Develops the ability to recognise UUID v1 as a systemic identifier weakness and leakage as a design-level exposure

Further Reading

  • RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace — IETF (Leach, Mealling, Salz)
  • OWASP API Security Top 10 — API1:2023 Broken Object Level Authorization — OWASP Foundation
  • UUID1 Vulnerability in Production Systems — Dan Kaminsky, blog post
  • Hacking APIs: Breaking Web Application Programming Interfaces — Corey Ball, No Starch Press (2022)

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.