OSCP Reference

10.3 Web Mapping Cheatsheet

Starting with a website?

Capture a working request and map the application before choosing a test.

Start the first checks →
Already have a suspicious input?

Choose a bounded test from the capability suggested by the evidence.

Follow the finding →

← Cheatsheet index · Complete HTTP procedure · Next: web exploitation · Mechanics | Strategy map | Study methods: Map useful web behavior

Use when: an HTTP(S) endpoint must become an evidence-labelled application map. Replace placeholders and keep each identity's cookies/tokens separate.

10.3.1 Establish the current state and choose your first useful check First five minutes

curl -skL -D headers.txt -o body.html http://TARGET:PORT/
curl -sk -o /dev/null -w 'code=%{http_code} bytes=%{size_download} type=%{content_type} redirect=%{redirect_url}\n' http://TARGET:PORT/
curl -sk http://TARGET:PORT/robots.txt
curl -sk http://TARGET:PORT/sitemap.xml

Record:

scheme://host:port | redirect/title/certificate | anonymous/authenticated role
METHOD PATH | INPUT | OBJECT/FUNCTION | STATUS/LENGTH/MARKER | NEXT TEST

10.3.2 Capture a working request and compare one controlled change Burp manual loop

Run/context: use the workstation's browser/proxy and preserve the actual application hostname, cookies and identity. Decide: a changed response needs a matched control, not just a status-code comparison. Select the next test through attack-input routing; if session or routing is broken, use common failure decisions before judging the input.

Scope target -> browse normally with Intercept off -> Proxy history
-> send interesting request to Repeater -> unchanged baseline
-> change one field/header/cookie/method/object -> compare -> save decisive pair

Replay curl through Burp:

curl -sk -x http://127.0.0.1:8080 -c cookies.txt -b cookies.txt http://TARGET:PORT/PATH

10.3.3 Find source, backups and configuration that reveal new leads Useful artifacts

curl -sk http://TARGET:PORT/.git/HEAD
curl -sk http://TARGET:PORT/openapi.json
curl -sk http://TARGET:PORT/swagger.json

Inspect HTML comments, hidden inputs, forms, JavaScript route strings, fetch/XHR calls, source maps, cookies and response headers.

10.3.4 Find unlinked application files and directories Content discovery

Calibrate with a random nonexistent path, then:

gobuster dir -u http://TARGET:PORT/ -w /usr/share/wordlists/dirb/common.txt -t 10 -o gobuster-root.txt
gobuster dir -u http://TARGET:PORT/ -w WORDLIST -x php,txt,bak,old,zip -t 10 -o gobuster-ext.txt

Authenticated:

gobuster dir -u http://TARGET:PORT/ -w WORDLIST -c 'SESSION=VALUE' -H 'Authorization: Bearer TOKEN' -t 10 -o gobuster-auth.txt

Confirmed soft-404 length:

gobuster dir -u http://TARGET:PORT/ -w WORDLIST --exclude-length NOISE_LENGTH -t 10 -o gobuster-filtered.txt

Check 200, redirects, 401, 403 and 405. A tool result is a candidate until manually reproduced.

Alternative engines, same decision:

feroxbuster -u http://TARGET:PORT/ -w WORDLIST -x php,txt,bak,old,zip -o ferox.txt
ffuf -w WORDLIST -u http://TARGET:PORT/FUZZ -ac -of json -o ffuf-content.json
wfuzz -c -z file,WORDLIST --hc 404 http://TARGET:PORT/FUZZ

-ac/status filters are starting points, not proof. Calibrate against random paths and compare stable body markers, lengths and redirects.

10.3.5 Find applications selected by another hostname Virtual hosts

gobuster vhost -u http://DOMAIN:PORT/ --append-domain -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -o vhosts.txt
ffuf -w WORDLIST -u http://TARGET:PORT/ -H 'Host: FUZZ.DOMAIN' -ac -o ffuf-vhosts.json
curl -sk -H 'Host: CANDIDATE.DOMAIN' http://TARGET:PORT/

Compare candidate and random Host responses before accepting a vhost.

10.3.6 Find inputs and object references that affect application behavior Parameters and object values

ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -u 'http://TARGET:PORT/PATH?FUZZ=test' -ac -o params-get.json
ffuf -w WORDLIST -u http://TARGET:PORT/PATH -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d 'known=value&FUZZ=test' -ac -o params-post.json
ffuf -w NUMBERS -u 'http://TARGET:PORT/api/objects/FUZZ' -H 'Authorization: Bearer TOKEN' -mc all -fc 404 -o object-values.json

10.3.7 Map API endpoints, authentication and object access APIs

curl -ski http://TARGET:PORT/api/v1/PATH
curl -ski -X OPTIONS http://TARGET:PORT/api/v1/PATH
curl -ski -X POST -H 'Content-Type: application/json' -d '{"username":"TEST_USER","password":"TEST_PASSWORD"}' http://TARGET:PORT/api/v1/login
PATH | METHOD | IDENTITY/ROLE | OBJECT/PROPERTY | RESULT | NEXT

405 often means valid route/wrong method. Validation errors disclose schema candidates. Verify every token through a separate authorized request.

10.3.8 Choose an input test from the behavior you observed Attack-input routing

Observed input/behaviorOpen
filename/path/template/download/uploadFile handling
diagnostic/archive/ping/URL or database-backed fieldCommand and SQL injection
object ID, role/property, admin API or rendered user inputCheck whether application permissions or browser execution enable useful access
server-side URL fetch, webhook, preview or importWordPress and SSRF
WordPress assets, REST routes or loginWordPress and SSRF
exact product/plugin/version candidateBlock 6 public exploits
credential/token/keyBlock 5, then remap authenticated behavior
verified OS commandBlock 7 session handling

10.3.9 Choose the next check from the failure you observed Common failure decisions

SymptomNext action
All paths return 200Measure a random path; filter only confirmed noise
Browser works, curl failsCopy exact Host/cookie/token/CSRF/method/content type from Burp
Repeated login redirectsRefresh auth context; use a separate cookie jar
403Compare random path; retry only with legitimate new identity
405Inspect Allow, docs and JavaScript; test supported method
Candidate disappears after filteringRemove filter and manually compare body markers

10.3.10 ffuf with the captured request

Save a manually verified raw request as request.txt and place FUZZ at one input. Preserve the correct Host, cookie and body. Choose the actual transport:

ffuf -request request.txt -request-proto https -w WORDLIST -mc all -ac -t 10 -o request-https.json
ffuf -request request.txt -request-proto http -w WORDLIST -mc all -ac -t 10 -o request-http.json

Replay outliers. Uniform login redirects → refresh the session; changing CSRF tokens → fix token handling before further fuzzing. Full mapping procedure.

10.3.11 Discover and recognize candidates

Use these discovery checks to find a candidate, then validate the missing conditions. Cues are illustrative; complete synthetic outputs and three-outcome examples are in the linked study entries.

10.3.11.1 Map useful web behavior

10.3.11.1.1 Find: Establish scheme, host, redirects and request state

Request the assigned HTTP endpoint without following redirects blindly; inspect location, cookies and alternate scheme/hostname behavior.

curl -skD headers.txt -o body.html http://TARGET:PORT/
curl -skI https://TARGET:PORT/

Recognize: The hostname/scheme redirect identifies the application request context to reproduce.

Validate next: Confirm the hostname routes to the assigned address and preserve its TLS/Host/session state.

Establish scheme, host, redirects and request state.

10.3.11.1.2 Commands and use-case variants

Need: A reachable HTTP application and recorded anonymous or authenticated request state. Correct scheme/port and virtual host; saved cookies/headers for authenticated comparisons

curl -skL -D headers.txt -o body.html http://TARGET:PORT/
curl -sk -o /dev/null -w 'code=%{http_code} bytes=%{size_download} type=%{content_type} redirect=%{redirect_url}\n' http://TARGET:PORT/

Decisive output: record the scheme, hostname/Host header, port, redirects, page title, certificate names, server/framework clues and whether the view is anonymous or authenticated.

10.3.11.1.3 Variant — explicit virtual-host candidate
curl -sk -H 'Host: CANDIDATE.DOMAIN' http://TARGET:PORT/

Compare it with a random hostname. A different status alone is weak evidence; compare body, length, title and redirects.

10.3.11.1.4 Variant — preserve cookies and follow redirects
curl -skL -c cookies.txt -b cookies.txt http://TARGET:PORT/PATH

Use a separate cookie jar per identity. Do not mix anonymous, ordinary-user and administrator evidence.

10.3.11.1.5 Variant — replay through Burp Community
curl -sk -x http://127.0.0.1:8080 http://TARGET:PORT/PATH

Confirm the proxy listener is active on 127.0.0.1:8080. Use -k only for the controlled lab because it disables destination-certificate verification.

Verify: Record final URL, host, status, redirects, cookies and authentication context before comparing payload results.

If it fails: A redirect loop or generic default page may indicate a wrong host or missing session rather than a nonexistent application.

10.3.11.1.6 Find: Map functions, roles and normal requests manually

Browse the site's normal account, export, upload and download features while recording requests in the browser/proxy.

curl -sk -b cookies.txt -D response-headers.txt http://TARGET:PORT/PATH

Recognize: The normal request exposes a file-selecting input discovered through functionality, not guessed from a payload list.

Validate next: Find the actual input semantics, account/role and normal response before file/read/authorization tests.

Map functions, roles and normal requests manually.

10.3.11.1.7 Commands and use-case variants

Need: A reachable HTTP application and recorded anonymous or authenticated request state. A normal request baseline and the relevant account/role; authorized accounts for role comparisons

For every visible function, capture one unchanged request in Burp Proxy history, send it to Repeater and record:

METHOD PATH | CONTENT-TYPE | ACCESS CONTEXT/ROLE
INPUT LOCATION + NAME | BASELINE VALUE
STATUS | LENGTH/HASH | REDIRECT | MARKER/ERROR/TIME
OBJECT/FUNCTION SELECTED | NEXT ONE-VARIABLE TEST

Check login/registration/reset, profiles/objects, search/filter/pagination, download/export/preview, upload/import, administration and every JavaScript API call.

Next: a browser-side restriction is not server authorization. Replay the raw request and change one field, object reference, method or access-context element at a time.

Verify: Retain method, route, input location, identity and expected normal behavior; do not infer vulnerability from an interesting parameter name.

If it fails: Expired sessions, CSRF failures and malformed requests can imitate access-control differences; reproduce a valid baseline first.

10.3.11.1.8 Find: Inspect source, backups, configuration and repository artifacts

Inspect linked JavaScript/source, robots/sitemaps, relevant backups and a bounded Git metadata check from the mapped web application.

curl -sk http://TARGET:PORT/robots.txt
curl -sk http://TARGET:PORT/.git/HEAD

Recognize: The path and Git reference are investigation leads; neither proves a working secret or complete repository.

Validate next: Compare missing-path controls, retrieve actual permitted artifacts and verify recovered history/account context.

Inspect source, backups, configuration and repository artifacts.

10.3.11.1.9 Commands and use-case variants

Need: A reachable HTTP application and recorded anonymous or authenticated request state. Readable application artifact or a complete recoverable repository; preserve the public-source scope

curl -sk http://TARGET:PORT/robots.txt
curl -sk http://TARGET:PORT/sitemap.xml
curl -sk http://TARGET:PORT/.git/HEAD
curl -sk http://TARGET:PORT/openapi.json
curl -sk http://TARGET:PORT/swagger.json

Also inspect HTML comments, hidden inputs, form actions, linked JavaScript, route strings, source-map references, cookies and response headers.

Decisive output: a path, parameter, API schema, object identifier, component or secret-bearing artifact that creates a specific next request. Source disclosure is not command execution.

curl -ski http://TARGET:PORT/.git/HEAD
curl -ski http://TARGET:PORT/.git/config

A readable HEAD/config supports exposed repository metadata. A 403, redirect or generic template is not proof. Preserve the correct host header/base path.

If authorized, recover into a new local directory with a purpose-built tool and inspect locally:

git-dumper http://TARGET:PORT/.git/ repo-output
git -C repo-output status
git -C repo-output log --oneline --all --decorate
git -C repo-output log -p --all

git-dumper is an optional third-party helper; install on demand in an isolated environment only when the exposure has been confirmed. Manual object recovery is possible but slower.

rg -ni 'password|passwd|token|secret|api[_-]?key|private[_-]?key' repo-output
git -C repo-output log --all -S'password' --oneline
git -C repo-output log --all -G'pass(word)?|secret|token' --oneline

Inspect candidate commits without dumping all history:

git -C repo-output show COMMIT -- PATH
git -C repo-output diff COMMIT^ COMMIT -- PATH

Validate freshness, identity and compatible use. Removed historical values are often rotated or environment-specific.

Verify: Confirm actual file/history content and distinguish a historical secret from a usable current credential.

If it fails: A 200 soft-404 or incomplete object database is not a recovered repository. Compare known-missing paths and record missing history.

10.3.11.1.10 Find: Discover directories and files with controlled response filtering

Establish the application's missing-path response, then run a bounded content search with the existing session/host context.

curl -sk -D - http://TARGET:PORT/KNOWN_MISSING_PATH

Recognize: The candidate's actual function differs from the soft-404 control despite equal status codes.

Validate next: Request a known-missing path under the same host/session and compare status, body and length. Open each distinct Gobuster/ffuf result; a uniform login page or soft-404 is a filter problem, not a directory finding.

Discover directories and files with controlled response filtering.

10.3.11.1.11 Commands and use-case variants

Need: A reachable HTTP application and recorded anonymous or authenticated request state. Correct base URL/session and a measured nonexistent-path response; bounded relevant wordlist

Request a random nonexistent path first and record its status, length and body marker.

gobuster dir -u http://TARGET:PORT/ -w /usr/share/wordlists/dirb/common.txt -t 10 -o gobuster-root.txt

Decisive output: manually verified routes including useful 200, redirect, 401, 403 and 405 responses.

10.3.11.1.12 Variant — technology-aware extensions
gobuster dir -u http://TARGET:PORT/ -w WORDLIST -x php,txt,bak,old,zip -t 10 -o gobuster-ext.txt

Choose extensions from observed stack evidence; do not spray every extension.

10.3.11.1.13 Variant — authenticated discovery
gobuster dir -u http://TARGET:PORT/ -w WORDLIST -c 'SESSION=VALUE' -H 'Authorization: Bearer TOKEN' -t 10 -o gobuster-auth.txt

Use only the cookie or header that applies. An expired session can turn every result into the same login redirect.

10.3.11.1.14 Variant — filter a confirmed wildcard body length
gobuster dir -u http://TARGET:PORT/ -w WORDLIST --exclude-length NOISE_LENGTH -t 10 -o gobuster-filtered.txt

Filtering without first confirming the noise response can hide a real path.

Verify: Open candidates and record their actual behavior; status/length alone is only a selection clue.

If it fails: Aggressive filters can hide genuine routes and rate limiting can fabricate differences; validate the baseline and reduce the request rate.

10.3.11.1.15 Find: Discover virtual hosts and hostname-selected applications

Collect hostnames from redirects, certificates, DNS and source; compare named requests against an invalid-host control.

curl -sk --resolve HOSTNAME:PORT:TARGET https://HOSTNAME:PORT/

Recognize: A reproducible hostname-selected application is a new mapping target on the same address.

Validate next: Send a random Host header as a negative control, compare the candidate's real response, then browse it with the correct hostname. A different status caused only by redirects or a default site is not a confirmed vhost.

Discover virtual hosts and hostname-selected applications.

10.3.11.1.16 Commands and use-case variants

Need: A reachable HTTP application and recorded anonymous or authenticated request state. A destination listener, relevant domain candidates and controlled Host/SNI routing

gobuster vhost -u http://DOMAIN:PORT/ --append-domain -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -o vhosts.txt

Alternative with automatic calibration:

ffuf -w WORDLIST -u http://TARGET:PORT/ -H 'Host: FUZZ.DOMAIN' -ac -o ffuf-vhosts.json

Failure cue: uniform status/length may be the default vhost. Compare each candidate with a random host header before adding it to the application map.

Verify: Compare candidate and nonexistent-host responses, including content and redirects; resolve to the intended scoped address.

If it fails: A default response for every host or an SNI mismatch makes the result inconclusive; do not treat every guessed hostname as a real application.

10.3.11.1.17 Find: Map parameters, API methods, objects and writable properties

Capture a valid API request, inspect its schema/client code and compare allowed methods and controlled object/role contexts.

curl -sk -i -b cookies.txt http://TARGET:PORT/api/PATH

Recognize: The actual object, method and writable input are known; returned owner/role fields are only candidate security boundaries.

Validate next: Determine field binding, ownership, persistence and server authorization with controlled accounts.

Map parameters, API methods, objects and writable properties.

10.3.11.1.18 Commands and use-case variants

Need: A reachable HTTP application and recorded anonymous or authenticated request state. A valid request and explicit role/object ownership; exact input format and content type

GET parameter names:

ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -u 'http://TARGET:PORT/PATH?FUZZ=test' -ac -o params-get.json

POST form parameter names:

ffuf -w WORDLIST -u http://TARGET:PORT/PATH -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d 'known=value&FUZZ=test' -ac -o params-post.json

Object values with an authenticated API:

ffuf -w NUMBERS -u 'http://TARGET:PORT/api/objects/FUZZ' -H 'Authorization: Bearer TOKEN' -mc all -fc 404 -o object-values.json

Decisive output: a manually reproduced parameter or value that changes application behavior. Tool outliers are candidates, not confirmed access-control flaws.

10.3.11.1.19 ffuf — preserve a captured authenticated request

Save a working raw request from the proxy as request.txt, retain its Host/cookie/body, and put FUZZ at the single parameter name/value or path being tested. Replay it once manually first. The request file does not specify TLS: choose the transport explicitly.

10.3.11.1.20 HTTPS request, including its original method and session headers

# HTTPS request, including its original method and session headers
ffuf -request request.txt -request-proto https -w WORDLIST -mc all -ac -t 10 -o request-https.json

10.3.11.1.21 Plain HTTP request: otherwise ffuf defaults to HTTPS

# Plain HTTP request: otherwise ffuf defaults to HTTPS
ffuf -request request.txt -request-proto http -w WORDLIST -mc all -ac -t 10 -o request-http.json

Read: compare an outlier's status/length/body with a known missing value, then replay that exact request. A login redirect for every value → refresh the session before continuing. A one-time CSRF token → repair token handling; the saved-request flag does not refresh it automatically.

ffuf request configuration.

curl -ski http://TARGET:PORT/api/v1/PATH
curl -ski -X OPTIONS http://TARGET:PORT/api/v1/PATH
curl -ski -X POST -H 'Content-Type: application/json' -d '{"username":"TEST_USER","password":"TEST_PASSWORD"}' http://TARGET:PORT/api/v1/login

Interpretation: 405 can establish that a route exists but rejects the method. Validation errors can reveal required fields. A token establishes only the authorization demonstrated by a later request.

Build a matrix across anonymous, user A, user B and administrator contexts where available:

PATH | METHOD | IDENTITY/ROLE | OBJECT/PROPERTY | RESULT | NEXT

Verify: Prove which input is consumed and whether state changes persist in an independent read.

If it fails: HTTP 400/415 may indicate encoding/schema rather than security enforcement. Keep a valid request before changing permissions-related properties.

10.3.11.2 Additional conditional surfaces

Open a branch only when its observation and prerequisites match. Discovery-only entries retain their missing-action boundary.

10.3.11.2.1 Map an authentication, session or multistep web flow

  • Enter: the application exposes login, registration, recovery, role change, state-changing business action, authenticated API or another session-dependent flow.
  • Discover: capture a working anonymous and/or authenticated request, then record method, scheme/host/path, headers, cookies/tokens, body fields, hidden values, redirects, role and each step required to complete the action. Include non-GET/POST methods, JSON/XML bodies and WebSocket/API messages when the application actually uses them.
  • Validate: replay the unchanged request first; then change one identity, object, property or session boundary at a time. Confirm freshness, CSRF/token coupling, object ownership and whether the result is server-side rather than a browser-only presentation change.
  • Execute: HTTP and web mapping, then route only the demonstrated effect to the existing parameter, authorization, IDOR, mass-assignment, XSS, parser or command/SQL method.
  • Verify: preserve one reproducible request/response pair and the exact role/session/object delta. Mapping a field or flow is not itself exploitation.
  • Outcomes: controlled unauthorized effect → application authorization or the matching primitive; invariant authorization/ownership enforcement → ruled out for that transition; token expiry, cache, redirect or client-side behavior masks the result → inconclusive/failed-boundary diagnosis.
  • Source: OWASP WSTG entry-point mapping.

Notes and interpretation.


Top of document · Reference home