views:

102

answers:

3

I'm trying to find a secure way to do the following:

  1. Users enters value into html form.
  2. Form is submitted.
  3. PHP uses submitted value as the argument for the "scandir" function.

My theory is include logic in the php script that forbids absolute paths and requires the directory name to include a certain value.

My concern is that a hacker could use my form to submit his own value and access sensitive files.

This is for a JQuery plugin. I don't want users to have to modify the PHP file.

How could the below code be hacked?

<?php

$foo = $_POST["some_directory"];

//validate $foo

//make sure path to directory is relative
$foo_url_test  = parse_url($foo);
if (isset($foo_url_test['scheme']) || isset($foo_url_test['host'])) {
$foo = NULL;
}

//make sure the directory name contains 'bar123'
$foo_name_test = preg_split('_[\\\\/]_', $foo);
$foo_name_test = end($foo_name_test);
$foo_name_test = strpos($foo_name_test,'bar123');
if ($foo_name_test === false) {
$foo = NULL;
}

//make sure the path does not contain '..'
$foo_dot_dot_test = strpos($foo,'..');
if ($foo_dot_dot_test == TRUE || $foo_dot_dot_test === 0) {
$foo = NULL;
}

//get files
$files_array = scandir($foo);

?>
A: 

Your directory name can contain .. elements, so they can look outside the current working directory you're intended to limit them to. They'll still only be able to look at directories named as you intend, though.

FWIW, using parse_url() to analyze whether a directory name is relative is really bizarre. Why don't you just look for $foo[0] == '/'?

(That assumes a Unix path convention, of course, but your code already does that.)

chaos
Thanks for the suggestion. I changed the code sample in my question to work for ms-dos or unix path types. Do you see any issues?
+2  A: 

You might want to look at realpath().

$foo = realpath($foo);
if (substr($foo, 0, 8) != '/my/path') {
    return false;
}

...or something like that.

deceze
+1  A: 

You probably need to elaborate further on the purpose of this script and why it wants to read arbitrary directories. Without this knowledge, it is difficult to comment on the security of this code, other than to point out it is an extremely dangerous thing to do, without clear limitations on accessible directories.

I, for one, would never install a PHP script to my server that allows a remote attacker to specify a directory to read - or even to be able to find out if particular files or directories even exist.

There is a strong argument for REQUIRING the user to edit a config file, read by the php, that allows the server owner to white-list a set of directories that are allowed to be opened by this script

Update after reply from OP

The problem you have here is that all "ajax" requests are made directly by and from the browser. This means that any data that the webserver sets in the html page that makes the ajax request can be overwritten by a malicious user. Your ajax request can be made by anyone at any time with any parameter, unless you secure it to do otherwise.

As soon as your data leaves your server, you can no longer trust it. The best way to make this secure is to hold a white-list of allowed directories on the server-side. If you receive a request for a directory that is not on the allowed list (or perhaps not in a subdirectory underneath something in the allowed list) then you reject the request and give a standard error response.

Cheekysoft
BTW: the plug delivers the directory name via AJAX to the php script, which returns html including image tags, etc. The plugin then adds that html to the web page.