Web Application Security Guide/File inclusion and disclosure
If the names of files that are to be included or sent in response to a request are coming from user input (e.g. in menu systems or download scripts), attackers may be able to request files that they are not supposed to. If user-supplied names are used for inclusions, this can even lead to code execution on the server.
To prevent this type of attack
- Do not take file names for inclusions from user input, only from trusted lists or constants.
- If user input is to be used, validate it against a whitelist. Checking if the file exists or if the input matches a certain format is not sufficient.
- Avoid having scripts read and pass through files if possible.
- If you read and deliver files using user-supplied file names, thoroughly validate the file names to avoid directory traversal and similar attacks and ensure the user is allowed to read the file.
- Ensure the application runs with no more privileges than required.
If the attacker is able to upload a script file and get a part of the application to include it, he can execute arbitrary code. As this poses an extremely great risk, it has to be carefully avoided. Thus, only the strictest kind of verification (checking against a whitelist) is appropriate for this task. If files are to be offered for download, simply putting them in a directory and letting the web server handle the rest is often the best choice: Not only is it faster than having a script read the file; it also avoids risky interpretation of user-supplied file names. In some cases, this is unavoidable, e.g. if a script is needed to enforce that only logged-in users can download files or to set special headers (see next section).
In that case, make sure you correctly perform the access checks that make the script-based approach necessary and that you thoroughly validate the file names to stop the attacker from downloading files he is not supposed to download. You especially need to make sure that the attacker cannot specify other files than intended, especially not outside of the intended directory, e.g. by using the “..” pseudo-directory name. (Note that a “../” can be encoded in many ways!)
Running the application with limited privileges (usually done by limiting the privileges of the web server or script interpreter) limits the impact of such (and other) issues.