Moving files out of a password-protected directory

danielcopelandnz56

New Member
Messages
9
Reaction score
0
Points
0
OK. The problem I have is this.

I have two main sections on my website so far: the public part, which anyone can access, and a password-protected directory.

The idea is that I'll put public pages in the public part, and admin pages in the protected directory. Admin pages will have functions for saving new files to the site.

Well, it's easy enough in PHP to save new files within the protected directory. You just give the new file name, e.g. "wibble.html", and you end up with a page like "www.mydomain.com/passwordplease/wibble.html".

And it's easy enough to put a script in the public part of the site which, when accessed, moves "passwordplease/wibble.html" to "wibble.html" -- that is, it moves it out of the protected directory.

But that's a serious security hole; if you knew about the page, you could move files out of the "passwordplease" directory without logging in.

And I can't figure out how to do either of the following:

  1. (my preferred option) -- put the mover script inside the "passwordplease" directory; it won't let you write to a URL beginning with "http://", and any partial URL you try and copy the new file to still will end up in "passwordplease"; or
  2. (if there's no easy way to do that) -- put a script in the public "movepage.php" script that checks whether you are logged in to "passwordplease" and won't move anything if you aren't; it doesn't appear in $_SESSION.
A little help?

EDIT: In case it's relevant and not clear: I made "passwordplease" a password directory using cPanel.
 
Last edited:

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
You should be able to save the file in any directory, not just the directory where the script is located.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
  1. (my preferred option) -- put the mover script inside the "passwordplease" directory; it won't let you write to a URL beginning with "http://", and any partial URL you try and copy the new file to still will end up in "passwordplease"; or
This, but you should be using filesystem paths, not URLs. HTTP URLs don't give you read access, and using FTP would be a waste.

Note that you can password protect individual files by editing .htaccess, using the Require (and accompanying) directives in a Files or FilesMatch section. See "Using FilesMatch and Files in htaccess" for an example.
 

danielcopelandnz56

New Member
Messages
9
Reaction score
0
Points
0
I've made the changes, but I can't tell whether they've worked because it's now telling me "open_basedir restriction in effect". What do I do?
EDIT for detail: this applies to the use of file_put_contents(). copy() has worked fine on previous tests.

---------- Post added at 06:49 AM ---------- Previous post was at 05:13 AM ----------

So I tried to do a workaround using copy() and rename(), but now I'm having the old problem again.

Specifically, this
PHP:
rename ("home/myname/public_html/passwordplease/".$tempname.".".$fileext, "home/myname/public_html/".$_POST ['Filename'].".".$fileext);
in a file within the passwordplease directory gets me this answer:
Warning: rename(home/myname/public_html/passwordplease/tempHTML.html,home/myname/public_html/newfilename.html) [function.rename]: No such file or directory in /home/myname/public_html/passwordplease/phptest.php on line 120
For the record, the copy() function worked fine, and public_html/passwordplease/tempHTML.html does indeed exist.

---------- Post added at 07:22 AM ---------- Previous post was at 06:49 AM ----------

PROBLEM SOLVED. Filesystem paths start with a forward slash. Thanks very much for the help!
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Your code fragment is most likely vulnerable to injection via $_POST ['Filename']. Someone could overwrite any file on the server that your account has write access to. Password protection of the script isn't enough, as you must plan against the possibility that someone will crack it.

On some OSs, you may have to deal with invalid filename characters; which characters are invalid depends on the filesystem. The X10 servers run Linux, which means they use extfs (in particular, the filesystem used on X10 currently is ext3). The only characters that are invalid in a file name under ext3 are "\0" (which PHP converts to an HTML character entity in form input) and "/" (which basename takes care of). Even though most any character is allowed in an extfs filename, it still is a good idea to be a little more restrictive in which characters you allow.

If the files being moved are not supposed to exist already, you can use file_exists to prevent overwriting of files.

Note that you can get the first part of the path from $_SERVER['DOCUMENT_ROOT'].

PHP:
function fsencode_piece($matched) {
    $matched = $matched[0];
    if ('-' == $matched) { # leading hypen
        return '%2D';
    } else if (' ' == $matched) {
        return str_repeat('_', strlen($matched));
    } else {
        return urlencode($matched);
    }
}

# Remove path, encode certain characters. Other encodings would also work. There 
# might be additional characters that should be added to the regex.
$filename = preg_replace_callback('/^-| +|(?:[^[:print:]]|[^\x20-\x7E]|["&*:<>?\\|])+/', 'fsencode_piece', basename($_POST['Filename']));
$source = "$_SERVER[DOCUMENT_ROOT]/passwordplease/{$tempname}.{$fileext}";
$destination = "$_SERVER[DOCUMENT_ROOT]/{$filename}.{$fileext}";
if (! file_exists($destination)) {
    rename($source, $destination);
}

Depending on your design requirements, you might want to make better use of PHP's file uploading[/php] feature, including the [URL="http://php.net/move_uploaded_file"]move_uploaded_file function.
 
Top