File Includes attacks
Another Web exploit (and one of my personal favourites, sadly out of the top 10 for now) . This is where the website designer has intended for external "chunks" of text to be included inside the page. Remember that programmers are lazy, so a lot of the time we try to reuse content between sites and applications.
To do this we make use of built in PHP functions such as:
- include()
- require()
- include_once()
- require_once()
Note
While we discuss PHP based includes attacks here, other dynamic web content languages can suffer from the same problems. For example ASP (https://www.w3schools.com/ASP/asp_incfiles.asp), or Node.js based applications are also vulnerable.
To understand includes, consider the following common example where we have a footer to be displayed on all pages of the website.
<footer>
<p>Copyright 2019: Foo@Bar.net
</footer>
We could then include this footer in all of our pages
<html>
<body>
<h1>Main page Title</h1>
<p>... Text Goes Here ...</p>
<!-- Include the footer -->
<?php include("footer.php");?>
</body>
</hmtl>
While examples like the one given in the example above are relatively harmless, if this value is based on user input (remember Rule #1) it is possible that we can inject code into the requesting page.
For example if includes was used to modify the text based on the value selected in a form supplied in a get request.
<h2>Option Selected</h2>
<?php include($_GET["thepage"]); ?>
This builds on the stuff we have learnt about with requests; if the user has any form of control over the resource being requested (so Cookies, HTTP headers or request parameters) then they can control the file being included.
This could be a traversal style attack allowing us to examine files
elsewhere on the target machine. More importantly, if the injected code
includes a <php?>
tag, the injected code may be executed by the PHP
interpreter.
Types of Include attacks
There are two key types of include attack: local and remote
Local File Includes are where the files that can be 'included' are on the server hosting the website. The threat level is a little bit lower, but there is opportunity for either file traversal, undefined behaviour, or in combination with a file upload dropping a remote shell.
Remote File Includes are less frequent (due to an update in the default PHP configuration) and require the allow_url_include being turned on in a config file by default. However, they give the ability to include a file from a remote server, which makes dropping a shell a trivial task.
Important
More recent versions of PHP have the allow_url_include option disabled by default However, its worth checking the config files.
General Considerations for File Includes
When considering file includes attacks there are a few other things we need to think about. These can affect the approach we take for the attack.
Types of file that can be included
The include function takes the contents of one file and inserts it into the other, before running the PHP processor over the result. This means that, as long as the input is text based, we can include files with any extension inside the generated source.
As an example consider the following:
-
quote.txt
“This must be Thursday,' said Arthur to himself, sinking low over his beer. 'I never could get the hang of Thursdays.”
-
Main.php
<h2>Quote of the Day</h2> <blockquote> <?php include("quote.txt"); ?> </blockquote>
Which is combined before rendering to become:
<h2>Quote of the Day</h2>
<blockquote>
“This must be Thursday,' said Arthur to himself, sinking low over his beer.
'I never could get the hang of Thursdays.”
</blockquote>
However, as the file is combined before parsing by the PHP interpreter, the contents of the included file are then potentially executable code. Consider what would happen if quote.txt contained, the following code.
“This must be Thursday,' said Arthur to himself, sinking low over his beer.
'I never could get the hang of Thursdays.”
<?php
phpinfo();
?>
The combined version of the file then contains valid PHP code, and will render the phpinfo() page.
<h2>Quote of the Day</h2>
<blockquote>
“This must be Thursday,' said Arthur to himself, sinking low over his beer.
'I never could get the hang of Thursdays.”
<?php
phpinfo();
?>
</blockquote>
Additionally, as the extension is not checked, this gives us some more freedom around how we get files onto a server to be included. For example, imagine a situation where we have both an includes style attack, and the ability to upload images. If the upload function ignores Rule #1, then we could rename the text file that we want to include to have a image extension (ie .jpg) and upload.
Working around extensions: The Null byte
One way of stopping this sort of attack is to attach the file extension outside of user input. This should mean that we have some control over the extension of files that are loaded.
For example, if we know we are expecting a .php
file to be
included. We have the form supply just the filename, (ie "data") then
append the extension server side. This can limit the types of files
included to only those with the correct extension.
The code to include files becomes:
<?php
if (!isset($_GET["lang"])){
include "eng.php";
}
else{
include $_GET["lang"] . ".php";
}
?>
Note
Again this is another option that no longer affects modern versions of PHP.
In versions of PHP <5.3.4 we were able to make use of C style string conventions to deal with this (currently this is patched, until the next flaw comes around).
Remember that strings in C are terminated with the NULL BYTE (0x00). If we inject one of these into the URL we can get to the page we are looking for.
Trying the URL http://172.17.0.3/includes/tryitnull.php?lang=foo.txt
Gives the following error as the script appends .php
to the filename, giving foo.txt.php
foo.txt.php
Warning: include(foo.txt.php): failed to open stream: No such file or directory in /var/www/html/includes/tryitnull.php on line 131
Appending a null byte means we may be able to get rid of the second PHP
part `ttp://172.17.0.3/includes/tryitnull.php?lang=foo.txt%00
.
foo.txt.php
Warning: include(): Failed opening 'foo.txt' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/includes/tryitnull.php on line 131
In versions of PHP > 5.4.3 the include directive still tries to get hold of foo.txt.php. Note that the string output (the second line) still sufferers from the null byte problem
Note
In the web trainer I have modified PHP to let this work in principle, as later version of PHP are not vulnerable to this flaw. However, there are still a lot of servers running PHP <5.4 -- therefore this may not work in the wild.
Summary
In this step we have introduced the concepts behind file includes attacks. This exploit relies on weak input sanitisation, and the attacker to place source code inside the page rendered by the server.
In the next steps we will examine both Remote and Local file includes in detail.
Further reading
File includes using PHP https://www.w3schools.com/php/php_includes.asp