I am new to the document storage space. I am not sure what i am doing yet, but before i begin i wanted to know about the possible security threats one has when one allows document uploads and what is the best way to sanitize the data? I am using PHP and will allow images, word docs, pdfs, excel docs, etc.
And is this a good solution:
http://blog.insicdesigns.com/2009/01/secure-file-upload-in-php-web-applications/
There are a vast amount vulnerabilities, when allowing a user to upload files. Potential, blocking unwanted file formats, can help limit the possibilities of someone being able to upload a shell, and root your server. Affecting the integrity, confidentiality and availability of information on your servers.
There also vulns within you forms control as well such as XSS (cross-site scripting) exploits...allowing a user to run malicious code. This could lead to malicious code being executed in users environments.
There also the possibilities, for vulnerabilities within your actual database as well i.e. SQL injections.
Just don't let the server execute executable files...
Risk from users uploading large files, utilising vital disk space and bandwidth.
Useful link for securing PHP upload scripts: http://www.webcheatsheet.com/PHP/file_upload.php
There are two really obvious ones:
If improperly done, a file uploader could allow the user to overwrite other people's files -- including the PHP that runs the site. Make sure permissions are set so that the web server's account has read-only access to any directory but where stuff should be written, and that nothing in that directory can be executed.
Users can upload (big) enough files to fill the site's disk quota. Even if they can't, they can try -- and the server might not refuse the upload til after the whole file's been sent anyway, chewing up precious resources and possibly still filling the drive (if only for the time it takes to refuse the request and delete the temp file).
And that's just the risks to the server. Files can contain malware that can affect other users. You'll probably want to find a scanner for that stuff.
I'll suggest that if you want to let people upload files, you find a pre-written script that a lot of other people use and recommend. Rolling your own is bound to cause you problems when someone does something that you never considered.
There are several threats you should be aware of:
Malware like virus, worms, trojan horses and so on, especially if the uploaded files are accessible by other users.
Files that can be executed on your system like php-files. If a user can upload a php-file to your webroot, he can execute arbitrary commands using something like passthru(cmd) or system(cmd).
Illegal content. You don't want anything illegal on your server that could get you into trouble.
Someone could upload HTML-files with javascript, using them for XSS attacks
...
Just to name some of them. You should take a look at the OWASP Website concerning Unrestricted File Upload. You should find anything you need there.
Related
Now I've read a bunch of SO topics on how to check whether PHP uploads are virus safe and the gist from that is: I can't 100% guarantee that uploads aren't full of viruses - no matter the extension. One proposed solution is to remove the extension during the upload and then reassemble it when people want to download.
However, I want to let users view files directly on the website. How do I go about doing that? For example, generating an iframe with an uploaded PDF inside - is that safe or is it like executing it which would give potential viruses the opportunity to spread? With DOCs I wanted to use Google Docs, so I'd embed an iframe of Google Docs which GETs a URL of the DOC on my server. Is that safe then?
Or is there simply no way other than only allowing downloads to prevent potential viruses from spreading on the server? If so, how goes the reassembling of the extension? I'd guess, when someone uploads a test.exe, I'd remove the .exe part but store in a database. Then when someone requests the download, i rename the test file to test.exe and push the download. After that I rename it back to test. Is that correct?
Also: how do services like Trello do this? When I upload an image file there, it gets shown directly - without noticeable delay through virus scans or whatever. I thought about using the virustotal.com API but that certainly takes quite long, doesn't it? Would it be okay though to let people upload, then not show them publicly until a virustotal.com-scan is done and then consider the file safe?
Thanks and cheers for all help and sorry, if I missed something.
There are a few approaches I've seen in practice over the years:
Scan it locally, using e.g. ClamAV.
Pro: If your virus detections are up-to-date, you'll catch any known viruses this way.
Con: Anti-virus software is an attack surface. See many of the findings of Tavis Ormandy from Google Project Zero.
Con: Could be taxing to server resources. (Maybe spin up a different server dedicated to AV purposes?)
Use an API, such as VirusTotal.
Pro: Less attack surface.
Con: You have to share the file with VirusTotal, which might be a bad idea if the files you're letting users upload are particularly sensitive (i.e. protected health information).
I'm not sure which to recommend, because I don't know your threat model or operational constraints.
However, the more general problem of not serving browser exploits (e.g. XSS) or allowing reverse shells on the server is actually somewhat easy, but not trivial.
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.
Writing a secure file upload PHP Script from the bottom sounds like hell to me.
The basic rules to uploading a file in no particular order:
1) Create a new file, something random, and give the new uploaded file that name
2) Check the extension
3) Check for the exif trick
4) Store all uploaded files off the web root, and give that directory no permissions to execute files.
5) make sure that the file upload function is PHP does not execute the code while uploading the file
6) Check the file size
7) Do some malware scan
8) limit filesize
So i am thinking thats a lot :)
I havent even begun writing a script for all this, because i have 3 basic questions.
1) Is my list complete, if something are missing please state which
2) is there some sort of framework that can do all this for me? Something simple, not a big huge one that can do multible other things.
3)
Is this a guide good?
http://www.sitepoint.com/file-uploads-with-php/
I would love to post code, but since this subject is big, i feel its better to ask larger.
Thanks in advance.
The “exif trick” and other measures in that article to sniff file contents are of little use in themselves. (OK, it's worth checking uploaded images are of the expected pixel size, but that's application-specific rather than a security problem.)
The article doesn't say what the threat model is that it's trying to address with filetype sniffing, but what this is commonly trying to do is prevent cross-site scripting attacks, where the attacker includes some active content in the file. Usually this is with HTML in files, which browsers (especially IE) sniff and decide to interpret as HTML even though that's not how the file is being served. Unfortunately, checking that a file begins with a PDF header, or represents a valid GIF image does not help you here because it's possible to make “chameleon” files that can be interpreted as different filetypes simultaneously.
This attack can be blocked in modern browsers by serving the files with a specific non-HTML Content-Type and an X-Content-Type: nosniff header. However there are more obscure attacks involving getting content into Flash or Java plugins that are not affected by this header, and it's not watertight against older browsers.
The really-safe way to stop XSS attacks on uploaded files is simply to serve them from a different hostname (ideally, a different domain name and IP address, but a simple subdomain is at least mostly-effective). Then you can let an attacker XSS the user-uploads-hosting site as much as they like without it having a negative effect on your main site.
Virus scanning is unlikely to prove useful for general-purpose file upload functions. If you are expecting people to use the site to exchange Windows executables then it can be worth scanning those for traditional malware, but for the general case you're typically concerned about attacks against the website itself—server exploitation, XSS, browser exploits—and those kind of attacks are not detected by AV scanners.
Your step (1) of creating a new random filename is a much better approach than “sanitising” user-supplied filenames as the linked article tries to do. Its “safe filename” function is not directly vulnerable to directory traversal, but it does still allow oddnesses like .. (on its own), the empty string, .htaccess, and filenames that would confuse a Windows server, like trailing dots, reserved names and over-long names.
You are right that secure file upload is much trickier than it initially seems, and unfortunately most tutorial code out there (especially for PHP) is pretty disastrous.
On of my client approached me to check and fix the hacked site. Site was developed by another developer , Very inexperienced developer not even basic security taken care of.
Well the problem was somehow PHP files were written to the images folder. Hackers also wrote an index.html which displays site is hacked. When I check images folder has 777 permissions. So I came to rough conclusion that its because of folder permissions. Hosting support guy says that some PHP file has poorly written scripts which allowed any extension file to upload to server, and then hackers executed files to gain access or do whatever they want.
I have few questions:
Is it only through upload functionality can we upload other PHP files ?
Is it not possible other way to write files from remote as folder permissions are 777?
Sit has some fckeditors editors and couple of upload functionalities. I checked them, there are enough validations , so when extensions other then images or PDF are tried to upload they just return false .
Does'nt setting folder permissions to lower level fix the issue?
I asked the support guy to change folder permissions and it would solve the issue, but he says there is some PHP file through of which other PHP files were written and he wants that to be fixed otherwise site cannot go live. He says even folder permissions are changed hacker can again change them to 777 and execute whatever he wants because that poorly written PHP file.
How should be my approach to find if there is such PHP file? Any help or pointers would be much appreciated.
777 means that any user on the system (with execute access for all the parent directories, anyway) can add anything to that directory. Web users are not system users, though, and most web servers (Apache included) won't let random clients write files there right out of the box. You'd have to specifically tell the server to allow that, and i'm fairly certain that's not what happened.
If you're allowing any file uploads, though, the upload folder needs to at least be writable by the web server's user (or the site's, if you're using something like suPHP). And if the web server can write to that directory, then any PHP code can write to that directory. You can't set permissions high enough to allow uploads and low enough to keep PHP code from running, short of making the directory write-only (which makes it pretty useless for fckeditor and such).
The compromise almost certainly happened because of a vulnerability in the site itself. Chances are, either there's a file upload script that's not properly checking where it's writing to, or a script that blindly accepts a name of something to include. Since the PHP code typically runs as the web server's user, it has write access to everything the web server has write access to. (It's also possible that someone got in via FTP, in which case you'd better change your passwords. But the chances of the web server being at fault are slim at best.)
As for what to do at this point, the best option is to wipe the site and restore from backup -- as has been mentioned a couple of times, once an attacker has gotten arbitrary code to run on your server, there's not a whole lot you can trust anymore. If you can't do that, at least find any files with recent modification times and delete them. (Exploits hardly ever go through that much trouble to cover their tracks.)
Either way, then set the permissions on any non-upload, non-temp, non-session directories -- and all the existing scripts -- to disallow writes, period...particularly by the web server. If the site's code runs as the same user that owns the files, you'll want to use 555 for directories and 444 for files; otherwise, you can probably get by with 755/644. (A web server would only be able to write those if it's horribly misconfigured, and a hosting company that incompetent would be out of business very quickly.)
Frankly, though, the "support guy" has the right idea -- i certainly wouldn't let a site go live on my servers knowing that it's going to be executing arbitrary code from strangers. (Even if it can't write anything to the local filesystem, it can still be used to launch an attack on other servers.) The best option for now is to remove all ability to upload files for now. It's obvious that someone has no idea how to handle file uploads securely, and now that someone out there knows you're vulnerable, chances are you'd keep getting hacked anyway til you find the hole and plug it.
As for what to look for...unfortunately, it's semi vague, as we're talking about concepts above the single-statement level. Look for any PHP scripts that either include, require, or write to file names derived in any way from $_GET, $_POST, or $_COOKIE.
Changing folder permissions won’t solve the issue unless you’re using CGI, since PHP probably needs to be able to write to an upload folder, and your web server probably needs to be able to read from it. Check the extension of any uploaded files!
(So no, 0777 permissions don’t mean that anyone can upload anything.)
As cryptic mentioned, once a hacker can run code on your server then you have to assume that all files are potentially dangerous. You should not try to fix this yourself - restoring from a backup (either from the client or the original developer) is the only safe way around this.
Once you have the backup files ready, delete everything on your your site and upload the backup - if it is a shared host you should contact them as well in case other files are compromised [rarely happens though].
You've identified 2 issues: the permissions and the lack of extension checking however have you any evidence that these were the means by which the system was compromised? You've not provided anything to support this assertion.
Changing the permissions to something more restrictive would have provided NO PROTECTION against users uploading malicious PHP scripts.
Checking the extensions of files might have a made it a bit more difficult to inject PHP code into the site, it WOULD NOT PREVENT IT.
Restoring from backup might remove the vandalized content but WILL NOT FIX THE VULNERABILITIES in the code.
You don't have the skills your client (whom is probably paying you for this) needs to resolve this. And acquiring those skills is a much longer journey than reading a few answers here (although admittedly it's a start).
Is it only through upload functionality can we upload other PHP files ? Is it not possible other way to write files from remote as folder permissions are 777?
There definitely are multiple possible ways to write a file in the web server’s document root directory. Just think of HTTP’s PUT method, WebDAV, or even FTP that may be accessible anonymously.
Sit has some fckeditors editors and couple of upload functionalities. I checked them, there are enough validations , so when extensions other then images or PDF are tried to upload they just return false .
There are many things one can do wrong when validating an uploaded file. Trusting the reliability of information the client sent is one of the biggest mistakes one can do. This means, it doesn’t suffice to check whether the client says the uploaded file is an image (e.g. one of image/…). Such information can be easily forged. And even proper image files can contain PHP code that is being executed when interpreted by PHP, whether it’s in an optional section like a comment section or in the image data itself.
Does'nt setting folder permissions to lower level fix the issue?
No, probably not. The upload directory must be writable by PHP’s and readable by the web server’s process. Since both are probably the same and executing a PHP file requires only reading permissions, any uploaded .php file is probably also executable. The only solution is to make sure that the stored files don’t have any extension that denote files that are executed by the web server, i.e. make sure a PNG is actually stored as .png.
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.