File inclusion vulnerabilities occur when developers use variables for dynamic file inclusion, and user control over these variables without proper validation allows unintended file access. These are most common in PHP. Local File Inclusion (LFI) involves server-local files, while Remote File Inclusion (RFI) requires specific PHP settings (allowurlinclude=on, magicquotesgpc=off). Key functions include include(), require(), and others like highlightfile() and filegetcontents(). PHP wrappers like file://, data://, php://, zip://, and phar:// enable various attacks, such as reading source code or executing commands. Vulnerabilities can be exploited for file reading, writing, or command execution, sometimes bypassing restrictions via log files or truncation. Prevention includes filtering dangerous characters, configuring openbasedir, upgrading PHP, renaming uploaded files, using whitelists, and applying least privilege for settings like allowurlinclude.
File Inclusion
1. Root Cause
To make code more flexible, developers set the file to be included as a variable to achieve dynamic invocation. If users can control this variable and the server does not validate the input — or the validation can be bypassed — a file other than what the developer intended gets included, resulting in a file inclusion vulnerability.
Tip
Almost all scripting languages provide file inclusion functionality, but file inclusion vulnerabilities are predominantly found in PHP. In JSP, ASP, and ASP.NET applications, they are extremely rare — practically non-existent.
2. Types of Inclusion Vulnerabilities
2.1 Local File Inclusion (LFI)
When the included file resides locally on the server, it constitutes a Local File Inclusion.
2.2 Remote File Inclusion (RFI)
Remote inclusion requires allow_url_include=on and magic_quotes_gpc=off
Both of these settings are in php.ini. When configured this way, the included file can come from a third-party server, enabling Remote File Inclusion.
3. File Inclusion Functions
include() — when using this function, the file is only included when code execution reaches the include() call. If an error occurs, only a warning is issued and execution continues.
include_once() — functions identically to include(), except that when the same file is called multiple times, the program includes it only once.
require() — require() differs from include() in that, if require() encounters an error during execution, the function outputs an error message and halts script execution.
require_once() — functions identically to require(), except that when the same file is called multiple times, the program includes it only once.
highlight_file()/show_source() — these functions apply syntax highlighting to a file, typically allowing the source code to be viewed.
readfile()/file_get_contents() — these functions read a file and write it to the output buffer.
fopen() — opens a file or URL.
4. Pseudo-Protocols
4.1 Overview
PHP has many built-in URL-style wrapper protocols that can be used with filesystem functions such as fopen(), copy(), file_exists(), and filesize().
Purpose: Used to access the local filesystem, typically for reading local files. It is not affected byallow_url_fopen or allow_url_include: When the parameter of include()/require()/include_once()/require_once() is controllable, importing a non-.php file will still cause it to be parsed as PHP code. This behavior is determined by the include() function itself.
4.2.2 Inclusion via data://
Prerequisites: allow_url_fopen = on: allow_url_include = on
Purpose: Typically used to execute PHP code. Starting from PHP >= 5.2.0, the data:// stream wrapper can be used to deliver data in the appropriate format.
4.2.3 Inclusion via php://
Prerequisites:
allow_url_fopen = off/on
allow_url_include = on (required only for php://input, php://stdin, php://memory, and php://temp)
Purpose: The php:// pseudo-protocol has many uses. The most common are:
resource=<data stream to filter>Required. Specifies the data stream you want to filter.
read=<read chain filters>Optional. One or more filter names, separated by the pipe character (|).
write=<write chain filters>Optional. One or more filter names, separated by the pipe character (|).
Any filter list not prefixed with read= or write= will be applied to either the read or write chain as appropriate.
Conversion filters:
convert.base64-encode — Base64 encoder
convert.base64-decode — Base64 decoder
4.2.3.2: php://input
Prerequisite: allow_url_include = on
A read-only stream that can access the raw data of a request, allowing data sent via POST to be executed as PHP code.
When the incoming parameter is treated as a filename to open, you can set the parameter to php://input and POST the file content you wish to use. PHP will then treat the POST body as the file content during execution.
Set file=php://input, then use Burp Suite to capture the request and inject PHP code.
HTTP
POST /include.php?file=php://input HTTP/1.1
HOST:
Accept:
<?php fwrite(fopen("shell.php","w"),'<?php eval($_POST(123));?>');?>
After sending the request, you will see that a one-liner web shell, shell.php, has been created locally.
4.2.4 Inclusion via zip:// & zlib://
The zip:// and zlib:// wrappers allow reading files from compressed archives. zip:// can access files inside .zip archives, while zlib:// handles gzip-compressed streams.
zip://[absolute path to archive]#[file inside archive]
?file=zip://D:\1.zip%23phpinfo.txt
Purpose: Both zip:// and zlib:// are compression stream wrappers that allow access to files inside compressed archives. More importantly, they do not require a specific extension — the archive can be renamed to any extension: jpg, png, gif, xxx, and so on.
4.2.5 Inclusion via phar://
The phar:// wrapper allows reading files from PHP archives (.phar files). It can be used to access files bundled within a phar archive, and can also be leveraged for phar deserialization attacks when combined with upload functionalities.
Truncation-based inclusion (%00): This method only works when magic_quotes_gpc=off. Some other truncation issues also existed in older versions of PHP.
Bypass via different protocols:
http/https
file
php
ssh2
6. Prevention Measures
Use functions like str_replace to filter out dangerous characters.
Configure open_basedir to prevent directory traversal. (open_basedir restricts the files PHP can open to a specified directory tree.)
Upgrade PHP to prevent %00 truncation.
Rename uploaded files to prevent them from being read.
Set up a whitelist for dynamically included files, and do not include files outside the whitelist.
Properly separate administrator privileges, enforce file permission management, and minimize the permissions for allow_url_include and allow_url_fopen.
1. Root Cause
To make code more flexible, developers set the file to be included as a variable to achieve dynamic invocation. If users can control this variable and the server does not validate the input — or the validation can be bypassed — a file other than what the developer intended gets included, resulting in a file inclusion vulnerability.
Almost all scripting languages provide file inclusion functionality, but file inclusion vulnerabilities are predominantly found in PHP. In JSP, ASP, and ASP.NET applications, they are extremely rare — practically non-existent.
2. Types of Inclusion Vulnerabilities
2.1 Local File Inclusion (LFI)
When the included file resides locally on the server, it constitutes a Local File Inclusion.
2.2 Remote File Inclusion (RFI)
Remote inclusion requires allow_url_include=on and magic_quotes_gpc=off
Both of these settings are in php.ini. When configured this way, the included file can come from a third-party server, enabling Remote File Inclusion.
3. File Inclusion Functions
4. Pseudo-Protocols
4.1 Overview
PHP has many built-in URL-style wrapper protocols that can be used with filesystem functions such as fopen(), copy(), file_exists(), and filesize().
4.2 Common Pseudo-Protocols
4.2.1 Inclusion via file://
4.2.2 Inclusion via data://
4.2.3 Inclusion via php://
4.2.3.1: php://filter
4.2.3.2: php://input
4.2.4 Inclusion via zip:// & zlib:// The zip:// and zlib:// wrappers allow reading files from compressed archives. zip:// can access files inside .zip archives, while zlib:// handles gzip-compressed streams.
4.2.5 Inclusion via phar:// The phar:// wrapper allows reading files from PHP archives (.phar files). It can be used to access files bundled within a phar archive, and can also be leveraged for phar deserialization attacks when combined with upload functionalities.
5. What Can Inclusion Vulnerabilities Be Used For?
5.1 Reading Files
Any special characters must be converted to Base64.
Example:
5.2 Writing Files / Command Execution
Only usable when allow_url_include is set to on.
Example:
5.3 Inclusion Bypass
6. Prevention Measures