I have a base path /whatever/foo/
and $_GET['path']
should be relative to it.
However how do I accomplish this (reading the directory), without allowing directory traversal?
eg.
/\.\.|\.\./
Will not filter properly.
The most effective way to prevent file path traversal vulnerabilities is to avoid passing user-supplied input to filesystem APIs altogether. Many application functions that do this can be rewritten to deliver the same behavior in a safer way.
Directory Traversal PreventionInput validation ensures that attackers cannot use commands, such as SQL injection that leave the root directory or violate other access privileges.
A path traversal vulnerability allows an attacker to access files on your web server to which they should not have access. They do this by tricking either the web server or the web application running on it into returning files that exist outside of the web root folder.
Note: While Path/Directory Traversal may seem similar to Local File Inclusion (LFI) and Remote File Inclusion (RFI), Path/Directory Traversal vulnerabilities only allow an attacker to read a file, while LFI and RFI may also allow an attacker to execute code.
Well, one option would be to compare the real paths:
$basepath = '/foo/bar/baz/'; $realBase = realpath($basepath); $userpath = $basepath . $_GET['path']; $realUserPath = realpath($userpath); if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) { //Directory Traversal! } else { //Good path! }
Basically, realpath()
will resolve the provided path to an actual hard physical path (resolving symlinks, ..
, .
, /
, //
, etc)... So if the real user path does not start with the real base path, it is trying to do a traversal. Note that the output of realpath
will not have any "virtual directories" such as .
or ..
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With