← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Double URL Encoding Bypass

security PHP 4.0+ Advanced

TL;DR

Filters operating on URL-decoded input miss double-encoded payloads — %2527 decodes to %27 which decodes to ' — always decode completely before filtering.

Explanation

URL encoding: %27 = '. Double encoding: %2527 = %27 = '. If a WAF or filter decodes once and checks, then the application decodes again, the second decode reveals the payload. Common in path traversal (%2e%2e%2f = ../), XSS (%253Cscript%253E), and SQL injection. PHP's urldecode() and $_GET automatic decoding create opportunities. Defences: filter after all decoding is complete, use parameterised queries (immune to encoding tricks), validate against a whitelist of allowed characters after normalisation, use realpath() to resolve paths before checking.

Common Misconception

URL-decoding input once before filtering is sufficient — attackers double-encode specifically to survive single-decode filters.

Why It Matters

Double encoding is a common WAF bypass technique — applications that rely on perimeter filtering without proper input normalisation remain vulnerable.

Common Mistakes

  • Filtering raw $_GET without checking if values are further encoded.
  • Path traversal checks that operate before realpath() normalisation.
  • Trusting WAF filtering without validating at the application layer.

Code Examples

✗ Vulnerable
// Checks for ../ but misses %2e%2e%2f or %252e%252e%252f:
if (strpos($_GET['file'], '../') !== false) {
    die('Invalid path');
}
readfile('/uploads/' . $_GET['file']);
✓ Fixed
$file = $_GET['file'] ?? '';
// Fully normalise before validating
$path = realpath('/uploads/' . $file);
if ($path === false || !str_starts_with($path, '/uploads/')) {
    http_response_code(400); die('Invalid path');
}
readfile($path);

Added 22 Mar 2026
Views 36
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 2 pings S 1 ping S 0 pings M 0 pings T 2 pings W 2 pings T 0 pings F 1 ping S 1 ping S 0 pings M 2 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Google 12 Perplexity 7 Amazonbot 6 Unknown AI 3 ChatGPT 2 Ahrefs 1
crawler 28 crawler_json 1 pre-tracking 2
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Use realpath() to normalise all paths before validation. Filter after complete decoding. Use parameterised queries. Never rely on encoding-based filtering alone.
📦 Applies To
PHP 4.0+ web
🔗 Prerequisites
🔍 Detection Hints
\$_GET|\$_POST|urldecode
Auto-detectable: ✗ No semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-22 CWE-79 CWE-116

✓ schema.org compliant