Skip to main content
See Security Labs

SEC504 - Hacker Tools, Techniques, and Incident Handling

IDOR and Forced Browsing: Enumerating Objects Nobody Should Reach

Solo, Lab

Focus: Web Application Security

Level: SEC504

Date: Jul 2026

Artifacts: Sanitized ffuf, curl, and browser output from the SEC504 web lab against support.falsimentis.com

TL;DR

  • ffuf content discovery found a /builds directory listing leaking a full Docker build log
  • A chatbot saved transcripts to predictable /chatlogs/chatlog-<id>.txt files with no authorization check
  • seq + ffuf -fc 500 enumerated 10,000 IDs in five seconds and pulled every user's chat log (IDOR)

Skills demonstrated

Forced browsing / content discovery with ffufReading robots.txt as an attack mapDirectory-listing and build-artifact analysisIDOR identification and object enumerationResponse-code filtering to separate hits from noise (-fc)

Note: Course-provided PCAPs and lab instructions are not shared. Only my own captures and sanitized notes are published.

Why this matters

IDOR is consistently near the top of real-world web findings because it needs no exploit, just a predictable identifier and a missing authorization check. Here a four-digit sequential ID plus no ownership check meant 10,000 requests, five seconds, and every user's chat log. This is the exact class of bug I hunt for in AppSec reviews: the object reference is right there in the URL, and the only thing standing between a user and someone else's data is a server-side check the developer forgot to write.

Context

This lab chains forced browsing (content discovery with ffuf) into an insecure direct object reference: a chatbot saves conversation logs to predictable, sequentially numbered files with no authentication, so enumerating the IDs exposes every user's transcript. It is a clean demonstration of two of the most common web findings, and how one feeds the other.

Tools used

ffuf 2.1.0curlseqFirefoxSlingshot Linux

Steps taken

1Read robots.txt

curl on robots.txt showed AI-crawler blocks and, for all agents, Disallow: /admin and Disallow: /singlestatus. robots.txt does not protect anything; it is a list of the paths the site most wants hidden, which makes it the first place to look.

$ curl http://support.falsimentis.com/robots.txt
Disallow entries are a map of sensitive paths, not access control

2Discover content with ffuf

ffuf fuzzed the URL path with a 128k-word list at ~2,200 requests/sec. Hits: admin, chat, contact, kb, status (all 200), and builds (302). The FUZZ keyword marks where each wordlist entry is substituted.

$ ffuf -w combined_words.txt -u http://support.falsimentis.com/FUZZ
FUZZinjection point
Default status matcher catches 200/301/302/401/403

3Investigate the builds directory listing

curl -v on /builds/ returned an 'Index of /builds' directory listing exposing build.log (80 KB) and build.log.old. Reading build.log leaked the entire Docker build: python:3.7-slim base, installed packages (including fping and netcat, relevant to the sibling command-injection lab), and every build stage.

$ curl -v http://support.falsimentis.com/builds/
$ curl -v http://support.falsimentis.com/builds/build.log
Directory listing + build log leak internal implementation detail

4Trigger the chatbot save

The /chat bot offered a 'save' command. Typing save returned 'Chat history saved!' and wrote the transcript to /chatlogs/chatlog-7341.txt. curling that file returned the transcript: a predictable four-digit ID, served with no authentication.

$ # in the chat UI: type 'save'
$ curl http://support.falsimentis.com/chatlogs/chatlog-7341.txt
Predictable 4-digit ID + no auth = the IDOR precondition

5Enumerate the log IDs

seq generated IDs piped into ffuf as a stdin wordlist. The first pass showed every nonexistent ID returned 500, so -fc 500 filtered that baseline out. Sweeping 0-9999 found live logs at 2305, 5492, 7127, 7341, and 9653 in 10,000 requests over five seconds.

$ seq -w 0 9999 | ffuf -w - -u http://support.falsimentis.com/chatlogs/chatlog-FUZZ.txt -fc 500
-w -read wordlist from stdin
-fc 500filter the baseline error code

6Retrieve another user's log

curling chatlog-2305.txt returned a complete conversation belonging to a different user. No credentials, no session, no ownership check: a predictable ID was the only thing between an anonymous request and another user's data. That is IDOR.

$ curl http://support.falsimentis.com/chatlogs/chatlog-2305.txt
Direct object reference with no server-side authorization

Key findings

robots.txt disclosed /admin and /singlestatus as sensitive paths
/builds directory listing leaked a full Docker build log
Chatbot saved transcripts to predictable /chatlogs/chatlog-<id>.txt with no auth
seq + ffuf -fc 500 enumerated 10,000 IDs in 5 seconds, exposing 5 users' logs

Outcome / Lessons learned

Chained forced browsing into an IDOR: ffuf discovered a directory listing leaking a Docker build log, and the chatbot's predictable, unauthenticated log filenames let a 10,000-request sweep pull every user's transcript in five seconds. Two of the most common web findings, one feeding the other.

Add a server-side authorization check on every object access so a user can only retrieve logs they own, and replace sequential IDs with unguessable identifiers (UUIDs) as defense in depth. Disable directory listing and move build artifacts out of the web root. Rate-limit and alert on high-volume 404/500 sweeps against a single path, which is the enumeration signature. Do not rely on robots.txt for anything but crawler hints.

Security controls relevant

  • Server-side authorization on every direct object reference
  • Unguessable identifiers (UUIDs) instead of sequential IDs
  • Directory-listing disabled; artifacts out of web root
  • Rate limiting and enumeration detection
  • Not treating robots.txt as access control

What I took away from this

IDOR is the finding I look for first in a review because it is common, high-impact, and needs no exploit. The whole vulnerability is a reference in the URL plus a missing check on the server. Here the reference was a four-digit number and the missing check was ownership, so anyone could read anyone's chat log. The fix is one authorization check per object access, and the fact that it is so often skipped is exactly why IDOR keeps topping the findings lists.

The enumeration technique is worth keeping. seq feeding ffuf on stdin, with -fc filtering the baseline error, turns 'is this ID valid?' into a five-second sweep of ten thousand possibilities. Sequential identifiers make it trivial; unguessable IDs make it impractical. That single design choice, UUID versus auto-increment, is the difference between a bug that is instantly enumerable and one that is not, which is why it belongs in the threat model of any object-reference endpoint.

Evidence gallery

IDOR and Forced Browsing: Enumerating Objects Nobody Should Reach | Luis Javier Lozoya