Null Byte Injection (%00) in LFI
The null byte %00 is a classic technique to bypass an extension filter in file inclusions (LFI) on PHP before 5.3.4. The vulnerable pattern is code that takes a user parameter and appends a fixed suffix before including it:
require_once($_GET['classes_dir'] . '/class.cs_phpmailer.php');Since the path always ends in .php (or .html, etc.), we cannot include /etc/passwd directly: the code would look for /etc/passwd/class.cs_phpmailer.php. This is where %00 comes in: in those PHP versions, paths are passed to C functions that read the null byte as end of string. Sending %00 discards everything the code appends afterwards, and the server includes exactly the requested file:
curl "http://<ip>/.../?classes_dir=../../../../../../etc/passwd%00" --path-as-isTwo payload details: the repeated ../ climb to the root (a few extra on purpose: overshooting is harmless, falling short fails), and --path-as-is stops curl from normalising the ../.
Combined with php://filter. If the goal is to read PHP source code (which would otherwise execute instead of being shown), wrap the resource in the php://filter wrapper with convert.base64-encode before the %00:
curl "http://<ip>/.../?classes_dir=php://filter/convert.base64-encode/resource=../../config.php%00" --path-as-is | base64 -dWhy it happens. One layer (PHP) builds a path from user input without canonicalising it, and another layer (the underlying C functions) treats \0 as a terminator. The same trick appears in old path traversals like CVE-2010-2861.
How to detect it. The access-log signature is a %00 (encoded null byte) in an inclusion parameter, often alongside ../ sequences and the php://filter wrapper; no legitimate request carries a null byte, so a WAF detecting it blocks it at once. A PHP < 5.3.4 banner is the preceding exposure, and the web process reading a file outside the expected tree (/etc/passwd, config.php) after that request confirms the traversal.
Defence. Upgrade PHP (in 5.3.4+ the %00 in paths stopped truncating), and above all validate and canonicalise any path built from user input instead of concatenating suffixes.
Machines where it's used
- PayDayProving Grounds Practice