PHP move_uploaded_file, what security does it provide - php

Wherever I look on the difference between PHP functions' rename and move_uploaded_file it always says that the difference is that move_uploaded_file have some security features.
My questions are:
what are those security features, what happen if I don't use it?
In case that I can't use it (I did an upload but not through POST) so I have to use the rename function, what security measures do I need to take?
Thanks.
Edit
#Pekka asked from me to elaborate of how I plan to upload the file.
I'm going to upload files through Ajax, and I have some queue feature for uploading multiples files. Therefore I'm using the php://input stream.
If I understand Pekka answer correctly, I have nothing to worry about since I'm getting the file as a stream and I'm not copying any temp file.
Please correct me if I'm wrong.

The background of this was an ancient, pretty bad vulnerability (in the early 2000s) in which you, instead of uploading an actual file, you could overwrite the tmp_file path with a local file path, leading to that local file being treated as the upload instead of the real uploaded file. (There was no $_FILES array back then.)
So for example, when uploading an avatar, the script would copy() the system file you specified (say, a configuration file ../../super_secret/config.php or a .htpasswd) to a public location and try to display it as the avatar image in a <img> tag.
Strangely, I'm unable to find any specific info on this vulnerability (I've searched a number of times already over the past couple of years), but I know for a fact it existed because I tested it myself. Any links are welcome.
As to what security measures to take, as said in the comment, I think you need to explain in more detail what kind of alternative file upload you are planning to use.

Related

PHP upload file without having to create a temp

So I am trying to use XAMPP server on ubuntu (Xampp 1.7.7 and yes, I know it is old) to upload files to a specific directory using PHP.
I know that it can be done, but every bit of code I can find wants to use a temp name. I think it checks to see if there is a duplicate file but can't I set it to just go strait to the directory? I know it wont be a problem so is this possible? Let me know if I need to be more specific.
Also, please don't ask "Why don't you want to use the temp directory?" because I don't want/need to is your answer. So if you have an answer, please let me know.
Thanks! :)
PHP couldn't care less about duplicate files. If two people upload "file.txt", PHP won't care, because it'll be using that nice random temp name instead. File collision handling is NOT php's job. that's up to your code.
And while it would be nice if you didn't HAVE to use a temp file for uploads, removing that restriction would mean a complete re-write of PHP's upload infrastructure. The script which a file upload is performed on is not invoked until AFTER the upload has completed (regardless of success). There is no mechanism in PHP to allow a "live" script to accept the upload as the bytes are streaming in.
If you need to handle the raw straw as the upload proceeds, you'll have to use some other language, e.g. perl.

is it dangerous to zip/unzip unknown uploaded files on server that may contain anything? even viruses?

i am trying to implement a user system (php, apache) where the user can upload several files and download a zipped version of them. (or uploading a zipped file and download the uncompressed files).
question: is there any risk to zip/unzip those unknown files?
in other words, are unix/php zip/unzip operations treat files as text only or some execution can occur?
This question is relevant to all compression methods, zip is just an example.
EDIT: #Alex Brown AND #Parallelis wrote 2 risks so obviously it is not safe.
any one can post a short explanation on how to implement a safe compress/uncompress of unknown files?
As It seems reasonable to me. You cant do this because of some issues, what if those files are bootstrap scripts? (Refer comments of Alex and Parallelis for 2 more issues).
Solutions :
If you going to store the zip files as zip files after being uploaded, Doing so you will face additional issues since zips can contain lots of files that may or may not be appropriate. In that case you may want to get a list of the contents of the file to automatically include in your field so people downloading them will know if the file contents are valid. You could also integrate with something like ClamAV to scan all the files that are uploaded.
Note: Google is doing same thing, they use their anti virus scanner programs (which offcourse are not available for public use).
Also you can place the file in a temporary directory first and then use zip_open on it in that location. Their you will be able to use OS level commands (which come with their own risks) to verify the integrity of the file without actually unzipping it. You can also refer this tool for same thing.
There are several potential issues:
Zip bomb - this is generally not that much of an issue any more because most decompression tools / languages will prevent nested levels of decompression.
Relative paths: This in my mind is your biggest concern - the zip is decompressed, but it includes the file: ../../../../../../vendor/autoload.php for example.. this then overwrites your autoload.php file and is executed whenever someone views your website. Game over.
A zillion inodes. A zip file may contain millions of 0 byte files, using up all your available inodes on the system. This would stop the hard disk being able to create new files on that partition. This could be medium-bad.
You also should know that zip archives could contain symlinks. If user can read files after unzip, it is possible to read arbitrary files on your filesystem.
zip utility has --symlinks option for storing symlinks.

Potential Security Issues with PHP's ZipArchive

I want to allow members the option of uploading content using a zip file. Once uploaded, I want to use PHP's ZipArchive class to decompress the zip file contents to a directory, and then move the files into our system.
I'm concerned about the potential security risks though, and I can't find any documentation on php.net. The first (Well, the only) risk that comes to mind, is someone creating a zip file with relative paths like "../../etc/passwd" (If they assume I decompress the file in /tmp/somedir).
I'm actually having a hard time creating a relative path in a zip file, so I can't test if such a thing would be possible. I also can't find any way to extract the contents of the zip file using ZipArchive, and have it ignore directories (Decompress all the files, but don't create the directory structure inside the zip).
Can anyone tell me if such an exploit is possible, and/or how to ignore the directory structure in a zip file using ZipArchive?
Interesting question, but I urge you to go about this a different way. I would highly recommend you run your web process with least privileges in a chroot jail. Assuming you do that, the WORST thing that can happen is your website get's defaced, and then you restore a backup and do some forensics to plug that specific hole.
New holes are discovered constantly, you will have a very difficult time completely securing your website going after hunches like these. Minimizing the attacker's sandbox really goes a long way.
I had the same concerns and had a look at the PHP 5.3 source code where I found this:
/* Clean/normlize the path and then transform any path (absolute or relative)
to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
*/
virtual_file_ex(&new_state, file, NULL, CWD_EXPAND TSRMLS_CC);
path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
if(!path_cleaned) {
return 0;
}
Looks fine to me. Checkout PHP and see ./ext/zip/php_zip.c for details.
You need to make sure that the extracted contents are not served directly by your application server. So if someone has a php file in his archive that he cant execute it via your webserver.
Another thing is you should keep things safe from being included in user generated content. But this should be considered also without having zip archives in place.
In the end I'm going with Pekka's solution, of using the command line unzip utility. It provides switches to ignore directories in the zip file. The concerns others have pointed out aren't an issue here. Once the files are unzipped, we add them to the system using the same process as our regular uploads, which means each file is scrutinized using the security measures we already have in place.

What are the difficulties/issues to consider when allowing ZIP file uploads?

I allow PDF files to be uploaded to my site (PHP).
I would like to offer the ability to also allow .zip files which contain PDF files in directories so it is easier for users to simply zip a directory and upload one file instead of uploading multiple zip files individual.
For those of you who offer a .zip file upload feature to your (PHP) website, what are the technical, security, and other issues you have faced?
Be careful how you unpack the zip, you could find yourself consuming far more resources than you expected. Perhaps some setrlimit(2) resource limits before unpacking would be wise.
The unzip(1) utility has several nice safety features built in; the -^ command line option turns off control-character filtering, so make sure you don't touch this :) and the -: command line option allows stupid pathnames like ../../../../etc/passwd. Make sure you're on at least version 5.50, so that those stupid pathnames are forbidden by default. (And don't use that command line option. I mention the options just so you can more easily find the documentation for them. :)
If you use an API, make sure it has options to prevent both kinds of silly filenames.
Assuming the .zip gets unpacked eventually you would have to make sure the directory they get unpacked in is unreachable by the the clients' browsers (with .htaccess or by placing it outside the web root directory), and even in that case I'd still monitor the contents of the unpacked .zip to make sure they didn't contain anything that might prove harmful (php or other files run by the server, html spoofs).
Another issue is i guess the upload_max_filesize set in php.ini, you can make sure it can be set big enough to suit your purposes before you start coding.
edit: also read sarnold's answer ;)
AFAIK, php can handle zip files pretty efficiently. Difficulties/Issues that I can think of is, while accessing the file where We need to extract the zip first, and then retrieve the actual needed file. Due to that reason, extracting a zip, might consume additional amount of server time, depending on the size of the file itself.
Where As, during uploads, I do not suppose there is any difficulties or issues specially emphasized on zip types.

Is it possible to block php scripts in upload folder?

I'm experiencing my first form in php where images can be uploaded.
I've seen some article on the web which explains it can be dangerous, so there is some way to block scripts on a specified folder? Something with .htaccess or php .ini instruction?
The VERY best way is to make sure that your upload directory is outside of your webroot. As long as the webserver has read/write access there you will be fine - no worries about executable uploads. This was discussed here on stackoverflow.
Your best bet is to verify the file's extension upon upload. If it's not jpg/png/gif/etc., dismiss it. As long as your webserver is not misconfigured to interpret any file as a PHP file, then with this approach you're out of harm's way, with minimal headache and really simple implementation.
Check the file being uploaded has a benign extension (.gif, .mp3, etc) - and trash anything else. For extra-sekrit protection, capture the file's original name in a database (for future reference), then encrypt the filename (and store that as well). That way anything that's uploaded can't be found by filename by the uploader.
It's dangerous only if you let the users upload whatever they want. Allow only what you decide is safe and you won't need to block anything.
i think it can be dangers if you don't check what file type was uploaded e.g. "hacker" uploads a php file that deletes all of your httpdocs stuff, or if people can upload to many or to big files.

Categories