Guide to local file inclusion

A number of web applications are constructed by including different files, occasionally these files can be specified in locations the user would have access to, cookies or a URL would be prime examples. On its own file inclusion isn’t a vulnerability, it’s used with the intention of building dynamic and easy-to-maintain applications. However, should a malicious user change the specified file, they may be able to include restricted or sensitive documents.

Here’s an example, let’s say we have a book website, this website includes a snippet from each book it sells. Readers are able to get a sneak peek at the contents before completing their purchase. In this example the snippet is provided by including a text file into the web page via the URL, here’s that URL.

https://vulnerable-website.com/book-snippet.php?file=The-Hobbit.txt

As you can see from the URL above, the file which will be included in the file is called The-Hobbit.txt. So, what would happen if the filename was changed to something else, like the Linux /etc/passwd file? Well, assuming the user has the file path correct and there aren’t sufficient protections in place then the file will simply be included as if it were the book snippet file, here’s an example of an exploited URL.

https://vulnerable-website.com/book-snippet.php?file=/etc/passwd

So, how does local file inclusion differ from other vulnerabilities such as path traversal? Where path traversal will simply allow an attacker to view another file, local file inclusion allows for the included files to be executed. To ensure the vulnerability is indeed local file inclusion an attacker will often try to include a known executable file such as index.php to see if the code itself is executed, this is how they will help confirm the vulnerability.

Firewall evasion techniques

Server administrators can often be over-reliant on web application firewalls to intercept path traversal/local file inclusions attempts, to do this they look for identifiers such as ../ and remove them from the request entirely. For example, see the following link.

https://vulnerable-bookstore.com/book.php?name=../../../etc/passwd

Once the request has passed through the web application firewall it would no longer have the ../. This is all well and good, however, what happens if someone submits a URL with ….// instead? Well, the firewall would still remove the ../, however, when it does this it would leave behind a ../ in the URL and so the filter would have been successfully bypassed.

Another method attackers might use to get around firewalls would be to URL encode their URLs, if this does not get decoded before it passes through the firewall then it would not recognise the harmful characters and allow the request. URL encoding is just a way for characters to get safely passed from browser to server, you’ll have often seen this in your web browser URL bar. Here’s an example of how our example URL would appear if it has been URL encoded.

https://vulnerable-bookstore.com/book.php?name=..%2F..%2F..%2Fetc%2Fpasswd

As you can see, all forward slashes have been replaced with %2F. Once the request has reached the server this would be decoded and would resemble the original URL.

What can local file inclusion achieve?

Local file inclusion can potentially be rather dangerous, along with including restricted files and exposing sensitive information, local file inclusion in some instances can be escalated to achieve remote code execution. Remote code execution is the process in which a malicious user is able to execute server-side code such as PHP from their browser, from here they could have the opportunity to perform command execution.

Preventing local file inclusion

As with many vulnerabilities, local file inclusion occurs due to the application trusting user input. One example to protect against local file inclusion would be to manually specify valid filenames, I’ll provide an example below.

 if(isset($_GET['page']) and $_GET['page'] == 'home') {
     include('home.php');
 }

Although the example above would help prevent any unspecified files from being included its not the most practical if you have a large number of potential files to be included. I’ll include another example below which would be more suitable for large-scale deployment.

<?php

    $filename = $_GET['page'].".php";
    $path = dirname(__FILE__).'/path/';

    if($filename != ".php"){

        if(in_array($filename, scandir($path))){
            include $path.$filename;
        }else{
            include $path."404.php";
        }

    }else{
        include $path."home.php";
    }

?>

As you can see from the code example provided, we’ve taken some additional steps to ensure only allowed files can be included. For example, the page is specified using the filename variable, this gets checked to see if it’s located within the specified directory, only if this file is present can it’s contents be included.

If the file does not exist within the specified directory then it’s contents won’t be included and a 404 document will be returned.

Spread the love