RCE Bypasses
Checklist
- Confirm there is a filter before you fight it. Baseline a clean payload first.
- Fingerprint the WAF so you pick known bypasses.
- Change one variable at a time: encoding, casing, separators, spacing.
- Keep an out of band probe so a blocked response still tells you something.
- Record the exact bypass that worked for the report.
A bypass is only worth it once you know a filter is in the way. If a plain ;id works, do not complicate it.
WAF fingerprinting basics
- Look at response differences: a 403, a scrubbed body, a block page, or a changed server header.
- Send a known bad string (for example
<script>or../../etc/passwd) and see what trips it. - Note the WAF name from block pages, cookies, or headers when present (Cloudflare, Akamai, AWS WAF, ModSecurity, Coraza).
- Behavior, not the name, drives the bypass. Test what is filtered: spaces, specific keywords, specific characters.
Command injection bypasses
When the obvious operators or keywords are filtered, change the shape without changing the meaning.
Spaces filtered:
${IFS}is the field separator:cat${IFS}/etc/passwd.- Brace expansion:
{cat,/etc/passwd}. - Tab or
$IFS$9in some shells.
Keyword filtered (for example cat):
- Quotes inside the word:
c""at,c'a't /etc/passwd. - Backslashes:
c\at /etc/passwd. - Variable splitting:
a=c;b=at;$a$b /etc/passwd. - Wildcards:
/bin/c?t /etc/passwd,/???/??t /etc/passwd.
Encoding and rebuilding:
- Base64 the whole command and decode at runtime:
echo aWQK | base64 -d | sh. - Hex or octal through
printf. $(rev<<<'di')style reversal to rebuild a word.
Separators filtered:
- Try the full set:
;,|,||,&&,&, newline%0a, and command substitution$(...)or backticks. - Carriage return plus newline
%0d%0asometimes passes where%0aalone does not.
Case variation:
- On case insensitive filters that still pass to a case sensitive shell, mixed case in keywords can slip through a naive regex, though the shell itself is case sensitive for binaries. More useful against the filter layer than the shell.
Comment insertion:
- In SQL to RCE contexts, inline comments
/**/replace spaces and break keyword matching:UNION/**/SELECT.
Shell alias and builtin evasion
- Call binaries by full path to dodge alias based blocklists:
/bin/catinstead ofcat. - Use alternate binaries for the same effect:
head,tac,less,nl,od,xxdall read files. - Use shell builtins:
while read l; do echo $l; done < /etc/passwd. execfamily andenvto launch:env cat /etc/passwd.
trap command bypass
- Some sandboxes wrap user commands and rely on shell traps or a restricted wrapper. A
trapset by the wrapper can sometimes be cleared or redefined, or you can start a fresh shell (bash -c,sh,exec bash) that does not inherit the restriction. - Restricted shells (rbash) block
cd,/, and redirection. Escape with a language one liner that spawns an unrestricted shell, for examplepython3 -c 'import os;os.system("bash")', or by invoking a program that can run commands (vi, awk, find-exec).
Pickle scanner bypass
- Defensive tools scan pickles for dangerous opcodes and known callables such as
os.systemorsubprocess. - Reach the same effect through less obvious callables:
ctypesto call libc, orpydoc.locate("os.system")to resolve the function indirectly so the literal name does not appear. builtins.evalorbuiltins.execreached through attribute lookup can also sidestep name based blocklists.- The lesson for defenders: name based scanning is weak. Only unpickle trusted data.
SpEL WAF bypass
- When
T(java.lang.Runtime)is filtered, reach classes reflectively:''.getClass().forName('java.lang.Runtime'). - Rebuild blocked strings character by character with
.charAt()and concatenation so the literalRuntimeorexecnever appears in the payload. - Use
#this,#root, and nested property access to get to a loader when direct type references are blocked. - Same idea applies to OGNL and MVEL: build the dangerous reference at runtime instead of writing it literally.
Chunked transfer and request smuggling basics
- Chunked
Transfer-Encodingcan split a payload across chunks so a WAF that inspects a single buffer misses the full string. - Request smuggling (CL.TE and TE.CL desync between a front proxy and the backend) can deliver a request the WAF never inspected, or poison the next user’s request. Confirm desync carefully with timing before weaponizing.
- These are powerful and risky. Use them only in scope and document the exact frames.
Rate limit evasion
- Rotate source IPs where allowed, and spread requests over time.
- Vary the request enough that simple signature caches do not short circuit.
- For OOB confirmation you often need only one request that lands, so patience beats volume.
Takeaway
Prove the filter, fingerprint it, then change one property at a time until the meaning survives. Keep the working bypass for the writeup. Continue to Reporting.