Uploading files

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Uploading files

Post by alex.barylski »

When uploading files and assuming your PHP is running under Apache user: nobody or apache. How do you ensure the security of the files system?

In order to allow PHP to upload a file and move it into a directory which is created by PHP shortly after upload, having a permission 777 is not good for safety.

775 is no better because then PHP can move files into the directory and/or edit/delete, etc.

Do you:

1) Run PHP as it's own user or use phpsuexec
2) Use FTP functions to change the permissions to 777 when uploading and back to 775 when finished?

The later is probably the best choice for widely distributed PHP applications, although I will likely have complete control over this environment.

Incase I missed a technique or a detail, what do you all think?
User avatar
infolock
DevNet Resident
Posts: 1708
Joined: Wed Sep 25, 2002 7:47 pm

Post by infolock »

You should only put files that are uploaded via a form to a non-http accessable directory.

In other words, upload them to /usr/local/www/my_uploads instead of /usr/local/www/htdocs/my_uploads

Then, when you are doing, move it to a directory that has like 766 or 755 or whatever. That's one quick step.

The next thing to do is check the header information and ensure that the file they are trying to uploads matches the file type you are expecting (img, txt, etc).

There are a million other things. I'm sure the others can shed more light on the subject.
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post by alex.barylski »

infolock wrote:You should only put files that are uploaded via a form to a non-http accessable directory.
That is one alternative, but unfortunately not available to me. I need the files accessible by web server and using a proxy script isn't an acceptable solution. Basically I need read only access to the files but my PHP scripts need write access, which complicates things, because PHP (in my case right now anyways) is running under user: Apache.

I'm wondering if I could just use some shell scripts which wrap native commands invoked by PHP through exec() to carry out moving files, deleting and creating file and directories...

If the shell scripts are "owned" by a user say "shell" then when invoked via exec:

Code: Select all

exec('createdirs.sh');
exec('deletedirs.sh /uploads');
exec('movefiles.sh /tmp /uploads');
When they created the folders as 755 any files moved into those directories via movefiles.sh would then only be readable by apache/PHP and not writable. Can I not achieve something like this using the SETUID flag under the permissions for each shell script???

Cheers :)
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Care to explain why a proxy script is not acceptable?
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post by alex.barylski »

I might have to go that route...but...

1) I may not always have access to outside of the docroot.
2) I have two folders which hold images and generic files. I glob those files and display them in a list inside a WYSIWYG, etc. When people edit the HTML which references those resources I would have to now find the file references and replace the URL with the proxy script instead. PITA essentially and additional processing.

Those two reasons had me seek an alternative. I thought originally I could use some shell scripts run under a different user, but now it seems that most *nix distro's frown upon that and don't actually obey the setuid flag on shell scripts - only executables.

My other alternative is to consider running PHP as CGI/PHPSUEXEC...this is the direction I think I will move in as it won't require substantial changes to existing source - hopefully.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Who says you have to replace the references to the files with the proxy script call?
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post by alex.barylski »

Well all the paths are currently:

Code: Select all

var/www/somedomain.com/uploads/images/
http://somedomain.com/uploads/images/logo.gif
If I move those files into:

Code: Select all

var/www/uploads/
Obviously the files will be broken.

I suppose I could use mod_rewrite to to convert requests into a proxy.php script, such that:

Code: Select all

proxy.php?file=var/www/uploads/
Is that what you were hinting at?

Cheers :)
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Hockey wrote:I suppose I could use mod_rewrite to to convert requests into a proxy.php script, such that:

Code: Select all

proxy.php?file=var/www/uploads/
Is that what you were hinting at?

Cheers :)
Yes.
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post by alex.barylski »

Sweet. That will actually work. :)

Can you tell me how to adjust the following mod_rewrite code I dug up:

Code: Select all

RewriteEngine on
RewriteBase /
RewriteRule ^blog/(.*)$ blog/$1 [L]
RewriteRule !\.(gif|jpeg|jpeg|cgi|js|ico|gif|jpg|png|css)$ index.php
This apparently feeds all requests through a front controller *except* when inside a directory called "blog". I need the opposite. I need everything to be ignored *except* anything inside an "uploads" directory. In which case I need to forward the request as well as the URL of the file onto proxy.php.

Then inside the proxy I guess I just check the extension, set the approriate headers and send back as a blob?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

If you put an .htaccess in the uploads folder, that alone will segregate the rewrite to only work against it. I bet you can figure out how to forward the request information from there... ;)
Post Reply