Skip to content
All posts
webrevised January 6, 20264 min read

Web recon: finding the endpoint the challenge is really about

The flag on a web challenge is usually behind a route the homepage never links to. Content discovery, JavaScript mining, parameter hunting, and reading the response headers - the reconnaissance that turns a blank page into an attack surface.

The most common way a web challenge stalls is not that the bug is hard - it is that you are looking at the wrong page. The vulnerable endpoint is /admin, /api/v2/debug, /backup.zip, or a parameter the form never shows you, and until you find it there is nothing to attack. Reconnaissance is the unglamorous half of web CTF, and doing it thoroughly is what separates people who solve web challenges from people who stare at the landing page.

This is a checklist for expanding a single URL into the full set of things you can actually poke at. Run it before you start attacking, and re-run it every time you learn something new - a discovered route often reveals a whole new area to enumerate.

1. Read what you were already given

Before any tooling, exhaust the free information. View source. Read every comment. Ask for /.git/HEAD - an exposed repository is one request and it hands you the source. Open the network tab and watch what the page requests. Check /robots.txt and /sitemap.xml - they exist to list paths, including ones the authors would rather you not visit. Look at cookies and, critically, the response headers, which name the server, the framework, and sometimes the version - each of which narrows what bugs are even possible.

2. Content discovery: brute the paths

The workhorse of web recon. Point a fast fuzzer at the site with a good wordlist and find the routes nothing links to. The art is in the wordlist and in reading the results, not in the tool.

ffuf -w wordlist.txt -u https://target/FUZZ -mc 200,301,302,403
# 403 is not a dead end - it means "this exists but you can't have it",
# which is exactly the kind of route a challenge wants you to reach.

# Then discover files, not just directories:
ffuf -w wordlist.txt -u https://target/FUZZ -e .php,.bak,.zip,.txt,.old,.git
Watch the status codes: 200 (found), 301/302 (redirect - follow it), 403 (exists but forbidden). Extensions matter: .bak, .old, and .zip of a known file leak source constantly.

3. Mine the JavaScript

A modern app's frontend JavaScript is a map of its backend. The bundle contains every API route the app calls, often route templates for endpoints not yet used, hardcoded keys the developer forgot were shipping to the client, and feature flags. Pull the scripts, pretty-print them, and grep.

# Extract endpoints and secrets from the JS bundles:
grep -oE '"/[a-zA-Z0-9_/-]+"' app.js | sort -u          # candidate routes
grep -oiE '(api[_-]?key|token|secret|password)["\x27:= ]+[^"\x27,}]+' app.js
# Tools like LinkFinder and the Wappalyzer/retire.js data automate this.
Route strings and key-shaped values are the two prizes. An endpoint referenced in JS but never called by the UI is often exactly the unguarded one.

4. Hunt for hidden parameters

Sometimes the route is obvious but the vulnerable input is a parameter the form does not expose - a debug=1, an admin=true, a file= that only works if you know to send it. Parameter mining fuzzes the query and body for names that change the response.

  • Guess the usual suspects. debug, test, admin, source, file, path, url, redirect, callback, id, page, lang, template.
  • Diff the response. A parameter that changes the output length, status, or timing is doing something - that is your lead, even before you know what.
  • Tools. Arjun and param-miner send hundreds of candidate names and report which ones the server reacts to, catching parameters no wordlist of routes would find.

5. Expand the host and the versions

Two more axes worth a look on larger challenges. Subdomains and virtual hosts - a dev., staging., or internal. host, or a Host: header the server treats specially, can expose a whole separate, less-hardened app. And API versioning - if /api/v2/ is current, /api/v1/ is often still mounted and missing a check the new version added. Old versions of anything are where the bugs the authors 'fixed' still live.

The recon loop

  1. Read the given surface: source, comments, network tab, robots.txt, headers.
  2. Content-discovery the paths and file extensions; check for .git and backup files.
  3. Mine the JavaScript for routes and hardcoded secrets.
  4. Fuzz for hidden parameters on the routes you have.
  5. Look for other vhosts/subdomains and older API versions.
  6. Every new find is a new surface - loop back and enumerate it too.