{
    "slug": "php_null_byte_file",
    "term": "Null Byte in File Paths (Legacy PHP)",
    "category": "security",
    "difficulty": "advanced",
    "short": "Null bytes (%00) in file paths truncated strings at the C level in PHP < 5.3.4 — PHP 5.3.4+ throws a warning, PHP 7 throws ValueError for NUL in paths.",
    "long": "In PHP < 5.3.4, a null byte in a string terminated C-level string functions. Attackers exploited this: include $_GET['file'] . '.php'; with file=../../../../etc/passwd%00 stripped the .php extension, including /etc/passwd. Fixed in PHP 5.3.4 — file functions now reject strings containing NUL. PHP 7 throws ValueError for NUL in filenames. Legacy codebases on older PHP: validate with strpos($input, chr(0)) !== false. Modern PHP (7+): not exploitable but still worth sanitising for defence in depth.",
    "aliases": [],
    "tags": [
        "php",
        "security",
        "null-byte",
        "legacy",
        "lfi"
    ],
    "misconception": "Null byte injection is fixed in all modern PHP — it is fixed in PHP 5.3.4+ and throws in PHP 7, but legacy codebases on older PHP remain vulnerable.",
    "why_it_matters": "Null byte injection in file paths bypassed extension validation and enabled arbitrary file inclusion on millions of PHP 4/5 sites.",
    "common_mistakes": [
        "Not upgrading from PHP 5.3.3 or earlier on legacy systems.",
        "Not sanitising null bytes in input even on modern PHP (defence in depth).",
        "Relying solely on extension append (.php) for security — null byte bypassed this."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "path_traversal",
        "lfi",
        "php_double_encoding",
        "php_stream_filter_injection"
    ],
    "prerequisites": [
        "path_traversal",
        "lfi"
    ],
    "refs": [
        "https://bugs.php.net/bug.php?id=39863"
    ],
    "bad_code": "// PHP < 5.3.4 — vulnerable:\n$file = $_GET['file']; // 'shell.php%00'\ninclude $file . '.php'; // Includes shell.php, ignores .php suffix",
    "good_code": "// Modern PHP (7+) throws automatically\n// Defence in depth — sanitise anyway:\n$file = str_replace(chr(0), '', $_GET['file'] ?? '');\n$file = basename($file); // Remove path traversal\n$path = realpath('/uploads/' . $file);\nif ($path === false || !str_starts_with($path, '/uploads/')) {\n    abort(400);\n}",
    "quick_fix": "Upgrade PHP to 7+. Sanitise with str_replace(chr(0), '', $input). Always use realpath() + path prefix check for file operations.",
    "severity": "critical",
    "effort": "medium",
    "created": "2026-03-23",
    "updated": "2026-03-23",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/php_null_byte_file",
        "html_url": "https://codeclaritylab.com/glossary/php_null_byte_file",
        "json_url": "https://codeclaritylab.com/glossary/php_null_byte_file.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Null Byte in File Paths (Legacy PHP)](https://codeclaritylab.com/glossary/php_null_byte_file) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/php_null_byte_file"
            }
        }
    }
}