How can I make sure the file path is in the given subdirectory?

I want to make sure that the file path set through the query string does not go beyond the required subdirectory. Right now, I am checking that:

  • The path does not start with " / " so that the user does not give an absolute path.
  • The path does not contain " .. " so that the user does not give a path that is outside the required subdirectory.
  • The path does not contain " : " to prevent the use of a URL (i.e., " http:// ", " ftp:// ", etc.). Should I ever run this script on a Windows server (this is not the case), this will also prevent absolute paths starting with the drive specifier (ie " C:\ "). Note. I know that a colon is a valid character in Unix file names, but I will never use it in a file name.
  • The path does not start with " \ ". Just in case, when I change my mind about working on a Windows server, this does not allow me to specify the Windows network paths (ie " \\someserver\someshare "). Again, I know that the backslash is a valid Unix file name character, but I will not use it in file names either.

Are these checks sufficient?

Background

I have a PHP script that takes (via the query string) the path to the sample source file that will be shown to the user. So I could give them a link like " view_sample.php?path=accounting_app/report_view.php " or " view_sample.php?path=ajax_demo/get_info.js ".

The script looks basically like this:

 $path = $_GET['path']; if(path_is_valid($path) && is_file("sample/$path")) { header('Content-Type: text/plain'); readfile("sample/$path"); } 

My concern is that the attacker will see the URL and try to do something like " view_sample.php?path=../../database/connection_info.php " and gain access to the file not in the "sample" directory.

Are the four checks listed above (which will be implemented in the path_is_valid() function) sufficient to block an attacker? (In addition, I believe that checks 1, 3, and 4 are mostly irrelevant, as I add a relative path, but if I did not, would there be enough checks?)

+4
security php sanitization
Jan 19 '09 at 4:42
source share
3 answers

Call

 $path = realpath("sample/$path"); 

Then verify that the resulting path starts with the directory you expect.

+10
Jan 19 '09 at 4:50
source share
 <?php // Current path information $path = $_GET['path']; $vroot = "sample"; // Validate that the $path is a subfolder of $vroot $vroot = realpath($vroot); if(substr(realpath($path), 0, strlen($vroot)) != $vroot or !is_dir($path)) {lid! exit("Invalid path"); } else { echo "Ah, everything is alright!"; } ?> 
+6
Jan 19 '09 at 5:39
source share

Using realpath should not change the path, so I use it in the following way:

 function checkPath($pathToCheck) { global $basepath; $fullpath = $basepath.'/'.$pathToCheck; if ($fullpath==realpath($fullpath) && is_dir($fullpath)) { return $fullpath; } else { error_die('path not allowed: '.htmlentities($pathToCheck)); } } 
0
Feb 26 '17 at 9:41
source share



All Articles