I have a simple form in PHP that make the conversion of a file from XML to SQL or vice versa. In this form, there is an input where the user can upload a file with xml or sql extension. I do various check (extension of the file and file size), I read the file using the value tmp_name of the global array $_FILES, I do some operation for the conversion, and then I save the modified file in my server (compressed in gz) with the original name of the file in the client machine in order to give the link to the user and download it.
My question are: There are risks of exploit with the steps that I listed above? In general, there are risks of exploit with uploading a file? Or risks, to upload the file with the original name in the client machine?
Thanks.
There are always risks of exploit when allowing users to upload files, so it's good to be worried.
You say "I do some operation for the conversion", so while I cannot comment specifically on the safety of this operation, there could be risks here depending on the operation and the content provided to it (e.g. buffer overruns, invalid data).
I'm assuming you are saving your file with a .gz extension.
Saving with the client filename could pose compatibility problems if you do not clean the filename at all. There are differences in disallowed (or problem) characters between filesystems, such as & in Unix or : on Windows. Sometimes if you simply save a file, and simply read it again your code won't "find" it, unless you escape or strip all these characters properly.
The client filename could possibly pose a risk, if the name could have for example a path embedded into it. A presented filename such as "../../../../home/user/file" could possibly trick your program into overwriting a file, as long as the permissions were very badly implemented and you are simply concatenating paths. At worst I'd say this would be an annoyance or DoS attack - limited to overwriting gzip files and "breaking" them.
The client filename could possibly overwrite another user's files? I'm not sure what your namespacing is, but a clever attacker could try to trick another user into downloading their xml/sql file by naming it cleverly.
Also if you could guess someone else's filename, you could guess the resulting URLs and war-dial through them looking for content.
All of these risks would go away, if you used a nice GUID to name the file. Or mapped it to each user's session (e.g. file1.gz is only valid to that user's session).
I generally don't use client names, or seriously validate and clean them before re-presenting them.
The main risk of uploading files with php (and other interpreted languages, as a matter of fact) is that user can upload a .php file and if it's stored inside a web-root, then execute it.
From your question, it seems you only allow certain non .php extensions. Make sure you do this check on server-side, not just on the client. Also, if you don't need to serve the uploaded file on web afterwards, store it outside of your web-root. If you force the filename and extension after upload (not keeping the original one), then you can have even more control over what's going on in your part of the system.
Other file types can also be exploited (images for example, see https://imagetragick.com/) so it's a good idea to check specifically for the file-types you want uploadable.
Related
We have a server that has been compromised that is running WordPress and Magento and is running them on about 5 domains all on the same server.
The hacker has been uploading there malicious scripts through all the file-system in hundreds of locations. It is a nightmare at this stage and I am still unable to find the entry point.
I did just notice that one of our AJAX image upload fields allows me to rename a PHP file as a .jpg and upload the file to the server.
When I access the PHP .jpg file in the browser is serves a broken image.
So I am not sure if the hacker would be able to upload a PHP file here and access it as a PHP file or if it would just serve it as a broken image fore like it did for me in the browser?
Any ideas on how much of a security threat this could be? Could it potentially be my entry point where hacker gained initial access? Or is the fact it serves as a broken image instead of processing the PHP file when I load in my browser mean that its somewhat secure?
Any help appreciated, thank you
Hard to say if the hacker has done something without actually checking what's there.
Regarding how to secure future image uploads I would advice using a function like finfo in PHP http://php.net/manual/en/function.finfo-file.php to find if a file belongs to any of the approved mime types, which btw, you should restrict to only a limited type of image types.
Also you should consider not allowing the use of the original image, but instead an adjusted version of it, to avoid that users end up downloading huge images or things like that.
Answer:
Usually (depending on the web server configuration) no one can execute a PHP file if it has a different extension, they could have upload it, but they can't run it, at least in any common configuration.
So, in theory you should not have to worry for that specific thing, but do be worry that someone is spending time in trying to hack you and that means you should expend time protecting the site and server.
I would recommend searching for articles on how to protect your specific server and configuration and to make sure you update your software, OS and such to the latest security updates.
Being able to upload a file with .jpeg file extension but PHP content is not a vulnerability in itself. However:
if the attacker is writing all over the file system you might have an upload function with a directory traversal vulnerability which will need fixing, ideally by not letting the uploader choose their own filename at all;
there are other problems to do with cross-site-scripting when you let users upload content to be served from the same hostname as the site;
it may be worth checking an uploaded file using something like getimagesize() to ensure that you have a JPEG file and non-ridiculous dimensions, but given the possibility of ‘chameleon’ files that can be interpreted as multiple different types this is not necessarily watertight, so this is a ‘defense-in-depth’ measure at best.
Getting a web server to run a .jpeg file as PHP code could happen by:
being able to write to server configuration to associate .jpeg with the PHP handler. Typically this would happen because another vulnerable file upload feature allowed an attacker to write a .htaccess file in the same directory for Apache to pick up.
a PHP script with a Local File Inclusion security hole. Typically this would be code like:
include("include/$variable");
where an attacker can get content into $variable, to point to something.jpeg. Generally include/require should never be used with variables unless those variables are explicitly limited to a few known-good values.
The other likely possibility if you have a load of malicious pages uploaded to your server is that your server login is compromised.
I am allowing users to upload files to my server. What possible security threats do I face and how can I eliminate them?
Let's say I am allowing users to upload images to my server either from their system or from net. Now to check even the size of these images I have to store them in my /tmp folder. Isn't it risky? How can I minimize the risk?
Also let's say I am using wget to download the images from the link that the users upload in my form. I first have to save those files in my server to check if they actually are images. Also what if a prankster gives me a URL and I end up downloading an entire website full of malware?
First of all, realize that uploading a file means that the user is giving you a lot of data in various formats, and that the user has full control over that data. That's even a concern for a normal form text field, file uploads are the same and a lot more. The first rule is: Don't trust any of it.
What you get from the user with a file upload:
the file data
a file name
a MIME type
These are the three main components of the file upload, and none of it is trustable.
Do not trust the MIME type in $_FILES['file']['type']. It's an entirely arbitrary, user supplied value.
Don't use the file name for anything important. It's an entirely arbitrary, user supplied value. You cannot trust the file extension or the name in general. Do not save the file to the server's hard disk using something like 'dir/' . $_FILES['file']['name']. If the name is '../../../passwd', you're overwriting files in other directories. Always generate a random name yourself to save the file as. If you want you can store the original file name in a database as meta data.
Never let anybody or anything access the file arbitrarily. For example, if an attacker uploads a malicious.php file to your server and you're storing it in the webroot directory of your site, a user can simply go to example.com/uploads/malicious.php to execute that file and run arbitrary PHP code on your server.
Never store arbitrary uploaded files anywhere publicly, always store them somewhere where only your application has access to them.
Only allow specific processes access to the files. If it's supposed to be an image file, only allow a script that reads images and resizes them to access the file directly. If this script has problems reading the file, it's probably not an image file, flag it and/or discard it. The same goes for other file types. If the file is supposed to be downloadable by other users, create a script that serves the file up for download and does nothing else with it.
If you don't know what file type you're dealing with, detect the MIME type of the file yourself and/or try to let a specific process open the file (e.g. let an image resize process try to resize the supposed image). Be careful here as well, if there's a vulnerability in that process, a maliciously crafted file may exploit it which may lead to security breaches (the most common example of such attacks is Adobe's PDF Reader).
To address your specific questions:
[T]o check even the size of these images I have to store them in my /tmp folder. Isn't it risky?
No. Just storing data in a file in a temp folder is not risky if you're not doing anything with that data. Data is just data, regardless of its contents. It's only risky if you're trying to execute the data or if a program is parsing the data which can be tricked into doing unexpected things by malicious data if the program contains parsing flaws.
Of course, having any sort of malicious data sitting around on the disk is more risky than having no malicious data anywhere. You never know who'll come along and do something with it. So you should validate any uploaded data and discard it as soon as possible if it doesn't pass validation.
What if a prankster gives me a url and I end up downloading an entire website full of malware?
It's up to you what exactly you download. One URL will result at most in one blob of data. If you are parsing that data and are downloading the content of more URLs based on that initial blob that's your problem. Don't do it. But even if you did, well, then you'd have a temp directory full of stuff. Again, this is not dangerous if you're not doing anything dangerous with that stuff.
1 simple scenario will be :
If you use a upload interface where there are no restrictions about the type of files allowed for upload then an attacker can upload a PHP or .NET file with malicious code that can lead to a server compromise.
refer:
http://www.acunetix.com/websitesecurity/upload-forms-threat.htm
Above link discusses the common issues
also refer:
http://php.net/manual/en/features.file-upload.php
Here are some of them:
When a file is uploaded to the server, PHP will set the variable $_FILES[‘uploadedfile’][‘type’] to the mime-type provided by the web browser the client is using. However, a file upload form validation cannot depend on this value only. A malicious user can easily upload files using a script or some other automated application that allows sending of HTTP POST requests, which allow him to send a fake mime-type.
It is almost impossible to compile a list that includes all possible extensions that an attacker can use. E.g. If the code is running in a hosted environment, usually such environments allow a large number of scripting languages, such as Perl, Python, Ruby etc, and the list can be endless.
A malicious user can easily bypass such check by uploading a file called “.htaccess”, which contains a line of code similar to the below: AddType application/x-httpd-php .jpg
There are common rules to avoid general issues with files upload:
Store uploaded files not under your website root folder - so users won't be able to rewrite your application files and directly access uploaded files (for example in /var/uploads while your app is in /var/www).
Store sanitated files names in database and physical files give name of file hash value (this also resolves issue of storing files duplicates - they'll have equal hashes).
To avoid issues with filesystem in case there are too many files in /var/uploads folder, consider to store files in folders tree like that:
file hash = 234wffqwdedqwdcs -> store it in /var/uploads/23/234wffqwdedqwdcs
common rule: /var/uploads/<first 2 hash letters>/<hash>
install nginx if you haven't done its already - it serves static like magic and its 'X-Accel-Redirect' header will allow you to serve files with permissions being checked first by custom script
I want to have an upload system on my website, where users can only upload images.
These images will be resized by PHP directly on upload, so the original image will not be stored.
Do I still have to worry about scripts like php, etc. executing from malicious images?
You still have the following attack vectors to consider:
The uploaded image will be stored for a certain time on the server and could be used for evil if there are bugs in your application.
Any byte trash uploaded as the image might trigger bugs in your resize code that reads the uploaded image, so it is important to stay up to date with this software or library.
Apart from that, the generated image should be considered safe.
Update:
Uploading images with PHP always results in a temporary file being created somewhere, possibly in an unknown "temporary file directory" location that everyone else on a shared host is also using. This file has a file name and possibly the malicious content. Although the filename is randomly generated, an attacker might be able to guess it and try to use it. On the other hand, you cannot protect yourself from this built-in php mechanism other than not to use unsafe include/require statements, because usually an attack requires a) getting evil code on your server and b) executing it.
Steps against it seem obvious: Configure a dedicated upload directory for your php. Secure it against code execution on the filesystem level by applying appropriate rights and restrictions. Don't mess with the random name generation. Keep this directory out of DOCUMENT_ROOT.
The second attack might be that an attacker tricks your code into reading a non-uploaded nonpublic file with the intent to reveal it's content. So it is a very good idea to check if the filename inside $_FILES really is an uploaded file before proceeding.
I've got a site that accepts user-uploaded files (images, pdfs, word docs, etc.) then allows other users to download them.
I realize this presents a security risk, since malicious users could upload scripts etc. that masquerade as useful files.
My question is this-- is it enough to check the mime type of the file being uploaded using PHP (mime_content_type or finfo) and set the file to read only (non-executable), or must I also store the uploaded files in a directory that is outside the web root? I would think this would eliminate most of the risk from the uploaded file, but I'm not sure. Performing a virus scan on uploaded files is not possible in this situation.
Thanks for input.
A common practice is to upload files outside the document root, and typically using randomized filenames which are then mapped to the correct item/object/post in the database. If additional permissions are needed to access the files, make sure you check them before allowing downloads, and of course you'll have only authenticated users uploading.
Fileinfo finfo_ is useful for validating most mimetypes, at least to verify that something called ".txt" is actually a text file and not a binary blob, or that a ".jpg" really appears to be a jpeg based on its first few or last few bytes. It may require some extra work sorting out MS Office mimetypes, as if I recall correctly, they all come out as application-msword. But you can then use the file extension to figure out what it is really supposed to be (xls, ppt, doc, etc).
A PHP script then supplies the downloaded file, rather than the web server directly serving it. For that reason, you should store the mime type along with it, so that you can serve the appropriate headers.
header("Content-type: application-whatever");
header("Content-length: size-of-the-file-in-bytes");
I can recommend you use every tool at your disposal to test for the file type. But know that there are other ways a hacker can implant a dangerous file.
Your best bet is to have the files be uploaded to a different server. One that can only host files.
I would check the mime type of the file but I wouldn't rely on this. Even if the file is a full blown .gif and contains a comment in its id3 tag which is a php, it can be executed with a local file include. A safer approach would be store files in the database using a long blob datatype. However this kind of overhead is crap.
The best solution from the perspective of security, scalability and perforce would be to use a no-sql database like CouchDB.
A few things to keep in mind, don't trust $_FILES[]. $_FILES['type'] could be anything the attacker wants so there is no point in checking it from a security perspective. And $_FILES['name'] could have nasty input like ../../../. Its best to rename files to the primary key and then store information about that file in a relational database (like mysql).
I am writing a small PHP application and I am not sure whether I have a security issue. So this is what the application does:
the user can upload either image files (png, gif, jpg, jpeg, tiff and a few others) or zip files
I check for mime-type and extension and if it's not an allowed I don't allow the upload (this is not the part I am worried about).
Now once uploaded I rename the file to a unique hash and store in a folder outside root access.
The user can now access the file through a short URL. I make the file accessible by setting the right mime-type for the header and then I just use readfile().
My question is whether the exploit where a jar file is included inside the image file works here? I am serving the image as a pure image.
If it does what are ways to prevent this?
Thanks.
MIME type checks will not solve the GIFAR issue. 2009's JREs are already patched, but if you want to solve the issue you can either
Serve your images from a different domain
Run a server side code to check if an image contains a valid JAR, like mentioned here
Anything else (short of denying the file to any Java enabled browser with an old enough JRE) may fail on specific cases.
Also remember that to perform a good attack with this technique your server infrastructure would have to be somewhat open (the fact that a request comes from the same domain doesn't mean that you should give any information it asks for.)
Checking the mime-type is not sufficient because that (or any other) HTTP header field can be forged. The best way to confirm that a file is a valid image is to attempt to read it as an image programatically. If it can be parsed as an image, you can be reasonably confident that it's not malicious code.
Related: ensuring uploaded files are safe
Any kind of hidden exploit like you describe should not affect the server because of the way you handle it. You're simply storing binary information, and retrieving binary information, without processing it in anyway. Browsers attempting to display exploited content might be at risk, but standard image types are fairly safe.
If you'd like to be safer, you could run an anti-virus on each uploaded file. If you're on a *nix platform, you can use the industry-standard ClamAV.
I'd be more worried of someone trying to upload a very large image file.
You can do 2 things. Serve your images from images.domain.com. this would have to be on another physical/virtual server, or firewall'd such that no open ports on the server can be accessed from that domain.
Or you can run the image file thru a java script (not javascript) like the one here. This will tell you if there is a jar file embedded in the image.
More info on this issue here:
http://www.gnucitizen.org/blog/java-jar-attacks-and-features/
I didn't actually even hear about this attack before your question, so first off, thanks for enlightening me! Googling around, it seems that there are basically two different attack vectors here. Both include the attacker luring "regular" users to a malicious site pointing to the masqueraded JAR file, and both have to do with the fact that the JAR will be executing in the "context" of your site (i.e. the origin will be your site).
First attack has to do with the applet being able to read user cookies, which basically means it'll be able to steal the user's login information for your domain.
The second one has to do with the fact that the applet is now allowed to open connections to other sockets within your domain, which is pretty bad if one of the users behind your server's firewall visits the malicious page (enabling the attacker to effectively bypass your firewall).
So this attack does not necessarily harm your server directly, but it does harm your users - and hopefully you care about your users. The two things you can do ensure their safety have already been mentioned in most of the other answers and are summarized on this page.