Local File Inclusion (LFI)

  •  

    Local File Inclusion

    Local File Inclusion (also known as LFI) is the process of including files on a server through the web browser. This vulnerability occurs when a page include is not properly sanitized, and allows directory traversal characters to be injected. A typical example of a PHP script vulnerable to LFI is as follows:

    <?php
    $file = $_GET['file'];
    if(isset($file))
    {
        include("pages/$file");
    }
    else
    {
        include("index.php");
    }
    ?>

     

     

    A legitimate request made to the script could look like this:

    http://example.com/index.php?file=contactus.php

     

    This is of little use to a potential attacker, who is more likely to be interested in the files outside the pages/ directory. To do this, an attacker could use LFI. The simplest example would be:

    http://example.com/index.php?file=../../../../etc/passwd

     

    On a *nix system, this would show the hashes of all passwords on the server, which could later be cracked and used to get file access.

     

    Filter Evasion

    Most good admins will have protected against the simplest LFI attacks, so we should take this sample script as a poor example:

    <?php
    $file = str_replace('../', '', $_GET['file']);
    if(isset($file))
    {
        include("pages/$file");
    }
    else
    {
        include("index.php");
    }
    ?>

    Now, our simple LFI attack will no longer work. Obviously, we don't want to be deterred by this, so we need to find a way for our directory traversal to work, while evading the filters. One way to do this is to encode one or more characters into hexadecimal. This works because the browser decodes the input, but PHP does not. Our new LFI would be:

    http://example.com/index.php?file=..%2F..%2F..%2F..%2Fetc%2Fpasswd

     

    Note: This is the wrong way to protect against lfi.  Because the following example could also evade this filter: (pay attention, you may be able to use this in a challenge on enigmagroup.org)

    http://example.com/index.php?file=....//....//....//....//passwd

     

    Why would this work?  Simple.  If you take the string above and filter the same way manually, it would remove only the ../ leaving this: ..   /  and since it replaces it with void space, it will become ../

     

    LFI Prevention

    There are a few methods to prevent LFI's.  Allow me to show you one of the most common. 

    <?php
    $include_dir = 'pages';
    $default_page = 'main';
    $account_root = '/home/username/public_html'; // no trailing slash
    
    $available_files = array(
    	'main',
    	'admin',
    	'gallery',
    	'contact'
    );
    
    $clean = array();
    $clean['page'] = (in_array($_GET['page'], $available_files)) ? $_GET['page'] : NULL;
    
    if (isset($clean['page']))
    {
    	$include = $clean['page'] . '.php';
    }
    else
    {
    	$include = $default_page . '.php';
    }
    
    if (is_readable($account_root . '/' . $include_dir . '/' . $include))
    {
    	include ($include);
    }
    else
    {
    	echo 'Invalid Page';
    	// or you can use header here to redirect to a 404 or any other custom page
    }
    ?>

     

    Original Author: hakipedia

    Revised and Extended: psychomarine

Comments

0 comments