If user data is present on generating parameters for the ‘include’ and ‘include_once’, or ‘require’ and ‘require_once’ functions, and the data is not filtered properly, the malicious user can gain access to files, previously locked for him. He could also execute scripts from a remote server
Incorrect User Input Filtration when Connecting to External Files

If user data is present on generating parameters for the ‘include’ and ‘include_once’, or ‘require’ and ‘require_once’ functions, and the data is not filtered properly, the malicious user can gain access to files, previously locked for him. He could also execute scripts from a remote server.

References

OWASP Top 10 2013 vulnerability: 4th place.

SANS Top 25 vulnerability: -.

CWE vulnerability identifier: CWE-98.

Example

Let’s take a look at a code fragment that is responsible for connecting language settings. Suppose the user language is stored as an HTTP cookie, and the default language is used if none exist.

Php
$lang = 'en';
if (isset($_COOKIE['lang'])){
    $lang = $_COOKIE['lang'];
}
include './languages/' . $lang . '.php';

Note: the call to ‘include’ can be replaced with ‘include_once’, ‘require’ or ‘require_once’.

Since the malicious user can control the parameters passed in cookies, he could set the value of ‘lang’ to

Data
../../../../etc/passwd%00

When decoding the parameters, the %00 will be treated as line termination [1]. When the ‘include’ function is executed, everything after the line termination will be ignored, which will connect the following file:

Data
./languages/../../../../etc/passwd

If the number of passes to the parent directory will be greater than the depth of the current one, the path will default to /etc/passwd, which will then be sent as the body of the HTTP request.

Potential consequences

This vulnerability can lead to execution of any code (if the malicious user connects a file from an external server [2]), or reading local files.

Removal recommendations
Php
$lang = 'en';
$languages = array('en', 'de', 'ru', 'cn');
if (isset($_COOKIE['lang'])){
    if (in_array($_COOKIE['lang'], $languages)){
        $lang = $_COOKIE['lang'];
    } else {
        //unsupported language specified
    }
}
include './languages/' . $lang . '.php';
Further reading