I'm doing a security audit on my friend's website. One piece of functionality is allowing users to upload files from html. The only validation is renaming the file to the current time stamp.
I was wondering, is there a way to upload a malicious file so that when a user goes to the url for that file, it executes code (on the server side)?
I tried uploading a hello-world php script, but it simply displays the code rather than executing it. If the file extension was .php, it would be executed, however, there is no file extension (because the file was renamed).
EDIT: I have access to the complete source code as part of the security audit. It would be better if I could solve this issue without using it, but I can answer any questions about the source code if needed.
As far as i know, uploading the file and visiting it via. the browser can not execute it server-side, unless the server is set to execute files without extensions.
However, if there's other vulnerabilities like Local File Inclusion you might be able to upload and execute a php script.
You can read a bit about File inclution here:
Wiki on RFI (almost the same) and here
Document on LFI and how it can be used
If you can execute the file or not depends allot on the server/sites setup, so you'll have to pen-test it you self to se if you can execute a php script.
The only thing you can do in a file with no extension is, as you mention your self, XSS, but only in older browsers (IE8 and down is vulnerable, most other browsers aren't.)
The security scanner Chorizo! might be of interest:
https://chorizo-scanner.com/
The solution was implemented by a company, which does daytime PHP consulting and coding.
It's a payed service. One scan is free.
Well, one thing that you would always remain at risk for is providing the possibility of getting malicious code onto the server - whether or not they would be able to execute it merely by viewing the URL of the specific file isn't all you have to think about.
If there was a vulnerability in YOUR code where you dynamically include or open local files on the server, then one could simply include the (now) local malicious code to be executed. Now granted this sort of attack is even common with people trying to include code on remote servers, but some setups are configured to prevent including remote files which would stop those attacks. Such a configuration would still leave you vulnerable if the code is physically on the machine and a weakness is found in your executable code.
That's just a thought - I wouldn't worry or panic too much about it, but I wouldn't entirely rule it out either.
From my understanding a lot of web output relies on reading files not actually executing them. A server will need specific permissions to execute a file.
The solution is firstly to check that the file types uploaded are allowed. If you are only uploading images - you don't expect a .php script. But this does not stop me creating bad.php and uploading it as bad.jpg.
I for example (on my ubuntu box) uploaded a php file with 777 permissions and could only run it by typing php hello.php. You would never normally do an include() on a file someone has uploaded so I believe most code relates to being readable.
Wikipedias page on File inclusion is a good start and includes a PHP example:
https://en.wikipedia.org/wiki/File_inclusion_vulnerability
Upload a file with javascript. There are plenty of js vulnerabilities.
http://en.wikipedia.org/wiki/Cross-site_scripting
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.
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.
So I'm a bit confused about what crafty users can and can't see on a site.
If I have a file with a bunch of php script, the user cant see it just by clicking "view source." But is there a way they can "download" the entire page including the php?
If permission settings should pages be set to, if there is php script that must execute on load but that I dont want anyone to see?
Thanks
2 steps.
Step 1: So long as your PHP is being processed properly this is nothing to worry about...do that.
Step 2: As an insurance measure move the majority of your PHP code outside of the Web server directory and then just include it from the PHP files that are in the directory. PHP will include on the file system and therefore have access to the files, but the Web server will not. On the off chance that the Web server gets messed up and serves your raw PHP code (happened to Facebook at one point), the user won't see anything but a reference to a file they can't access.
PHP files are processed by the server before being sent to your web browser. That is, the actual PHP code, comments, etc. cannot be seen by the client. For someone to access your php files, they have to hack into your server through FTP or SSH or something similar, and you have bigger problems than just your PHP.
It depends entirely on your web server and its configuration. It's the web server's job to take a url and decide whether to run a script or send back a file. Commonly, the suffix of a filename, file's directory, or the file's permission attributes in the filesystem are used to make this decision.
PHP is a server side scripting language that is executed on server. There is no way it can be accessed client side.
If PHP is enabled, and if the programs are well tagged, none of the PHP code will go past your web server. To make things further secure, disable directory browsing, and put an empty index.php or index.html in all the folders.
Ensure that you adhere to secure coding practices too. There are quite a number of articles in the web. Here is one http://www.ibm.com/developerworks/opensource/library/os-php-secure-apps/index.html
I have a simple site which allows users to upload files (among other things obviously). I am teaching myself php/html as I go along.
Currently the site has the following traits:
--When users register a folder is created in their name.
--All files the user uploads are placed in that folder (with a time stamp added to the name to avoid any issues with duplicates).
--When a file is uploaded information about it is stored in an SQL database.
simple stuff.
So, now my question is what steps do I need to take to:
Prevent google from archiving the uploaded files.
Prevent users from accessing the uploaded files unless they are logged in.
Prevent users from uploading malicious files.
Notes:
I would assume that B, would automatically achieve A. I can restrict users to only uploading files with .doc and .docx extensions. Would this be enough to save against C? I would assume not.
There is a number of things you want to do, and your question is quite broad.
For the Google indexing, you can work with the /robots.txt. You did not specify if you also want to apply ACL (Access Control List) to the files, so that might or might not be enough. Serving the files through a script might work, but you have to be very careful not to use include, require or similar things that might be tricked into executing code. You instead want to open the file, read it and serve it through File operations primitives.
Read about "path traversal". You want to avoid that, both in upload and in download (if you serve the file somehow).
The definition of "malicious files" is quite broad. Malicious for who? You could run an antivirus on the uplaod, for instance, if you are worried about your side being used to distribute malwares (you should). If you want to make sure that people can't harm the server, you have at the very least make sure they can only upload a bunch of filetypes. Checking extensions and mimetype is a beginning, but don't trust that (you can embed code in png and it's valid if it's included via include()).
Then there is the problem of XSS, if users can upload HTML contents or stuff that gets interpreted as such. Make sure to serve a content-disposition header and a non-html content type.
That's a start, but as you said there is much more.
Your biggest threat is going to be if a person manages to upload a file with a .php extension (or some other extension that results in server side scripting/processing). Any code in the file runs on your server with whatever permissions the web server has (varies by configuration).
If the end result of the uploads is just that you want to be able to serve the files as downloads (rather than let someone view them directly in the browser), you'd be well off to store the downloads in a non web-accessible directory, and serve the files via a script that forces a download and doesn't attempt to execute anything regardless of the extension (see http://php.net/header).
This also makes it much easier to facilitate only allowing downloads if a person is logged in, whereas before, you would need some .htaccess magic to achieve this.
You should not upload to webserver-serving directories if you do not want the files to be available.
I suggest you use X-Sendfile, which is a header that instructs the server to send a file to the user. Your PHP script called 'fetch so-and-so file' would do whatever authentication you have in place (I assume you have something already) and then return the header. So long as the web server can access the file, it will then serve the file.
See this question: Using X-Sendfile with Apache/PHP
I've just had an argument with a colleaque.
My index.php contains my mysql connection and therefor also the host, username, password and database name.
He claims it is a security thread for the possibility exists that the php parser may fail which would cause the webserver to return the entire file as plain text.
I however believe that IF the php parser would fail the webserver would give an internal server error to the users.
Can anyone confirm whether it is or is not a security risk?
thank you.
The short answer is no.
The long answer is yes, but only if:
your server's been compromised, in which case people reading your php files are the least of your worries
you've misconfigured your server to parse .php files and plain text, which would be very silly indeed.
Also, if you're using some kind of version control software, make sure your .hg or .svn or whatever folders can't be viewed from a web browser. You'd be surprised how often that happens.
EDIT:
I would be inclined to go with some of the suggestions on here already, which is what I do in my day to day development. Have a config.php file outside of your web root folder and include this in your index.php. That way you know for sure it's never going to be viewable. Btw, I've been developing in PHP for a number of years and have never had the parser fail in such a way that it's resulted in raw PHP being displayed to an end user.
EDIT 2:
If your colleague is referring to parse errors when he talks about the PHP parser "failing" then in a live environment you should have error reporting disabled anyway.
Either outcome is a possibility. The normal course of action is to use require to bring in a separate file containing your db credentials. That file should be outside the webserver file tree so it can't be reached via a browser.
I'm in the belief that you can never be too safe. What's easier, replacing thousands, possibly millions of records if a hacker gets your db information, the security breach you would have to explain to your users (and possibly their lawyers depending on content and breach) or putting your db information in a separate, password protected folder and including the information on the pages you need the connection?
To me, the choice is simple.
Your co-worker is correct but this is very unlikely to happen. The .php file will only be returned as plain text or as a download if PHP has stopped running on the host.
To be safer, use an include() path to the database credentials in a new folder. In that folder have a .htaccess file with 'deny from all'.
That way even if PHP stops running on the server, Apache will still run and protect all the files including the database credentials. If even apache stops running, the whole webserver will be unreachable and your credentials will still be safe.
:)
Personally I'd put the options in a config file outside the web tree and, once uploaded, remove FTP access from that directory. It's not just a matter of whether the PHP parser fails and drops the file out as plain text BUT if the FTP server has a vulnerability that's compromised that file could be accessed by FTP as well as HTTP.
As long as Apache/PHP is running as a separate user to FTP you can still require the config file from PHP.