Skip to content

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

Back to top