External image vulnerabilities - php

What security holes can appear on my site by including external images via img tag and how to avoid them?
I'm currently only checking the extension and mime-type of image on submission (that can be changed after URL is submitted) and URL is sanitized before putting it in src attribute.

There's probably a differentiation to be made here between who is at risk.
If all you're doing is storing URLs, and not uploading images to your server, then your site is probably safe, and any potential risk is to your users who view your site.
In essence, you're putting your trust in the reliability of the browser manufacturers. Things might be fine, but if a security hole in some browser one of your users uses were to arise that involved incorrectly parsing images that contain malicious code, then it's your users who will end up paying for it (you might find GIFAR interesting).
It comes down to whether you trust the browser manufacturers to make secure software, and whether you trust your users to not upload URLs to images that might contain exploits for certain browsers. What might be secure now might not be secure come the next release.

The primary holes that can be exposed are those where corrupted images cause buffer overflows within the browser, allowing arbitrary code execution.
If you're only putting the images into an <img> tag there shoudln't be any vulnerabilities relating to sending alternative MIME types, but never underestimate the stupidity of some web browser developers...

Well, obviously, you're not doing any checks on the data, so the data can be anything (the mime-type reported by the remote server doesn't necessarily tell the truth). Plus, as you said, the data on the remote server can be changed since you're never looking at it after submission.
As such, if the link is put into lets say an <img src="..."/>, then any vulnerability that a browser might have in the image handling can be exploited.
"Sanitizing" the URL doesn't help with anything: somebody submitting a link that points to a 'bad' image isn't going to attack his own server.

Related

Src images and security

What about if I let users insert links to their own host's images, do I need to prevent any type of security issue?
To better exaplain, <img src="somedomain/somefile"/> in which case should make my site vulnerable?
One potential problem with allowing arbitrary image URLs is that the image's host could track all views and IP addresses. In a forum with little traffic that could put the image host in the position to identify specific users' IP addresses.
Another is that you don't control what is shown in the image. An image resource could be dynamic and show pretty much anything at any given time to any user.
Then there's the very remote risk of an image exploiting a vulnerability in a visitor's browser or image library. But those are exceedingly rare and likely to get patched quickly - I myself know of only one instance this has happened on a larger scale.
Stack Overflow with is massive reach and traffic still allows external images - from that I tend to deduce that the risks are somewhat manageable.
Still, if you want to make really sure, you're best off fetching the image resource, copying it using an image library (to make sure it's a real image and to strip any sensitive metadata), and storing it on your server.
Also if you're doing a simple string insertion into your markup someone could close the image tag and start a script tag or something like that. So you should be watching for script injection in whatever form the user gets to set such an image src attribute.
For example what if the image src was set to this:
myimagefile.jpg" /><script> ... </script>
You can see how that would get rid of the image tab altogether and start doing something else in a script tag. You need to make sure whatever they enter actually points to an image before you save it and start writing it out on live pages.
This style of script injection could for example read from a form on the page (maybe including personal information, login details, or session ids) and send end users info back to some bad hackers data collection point using jsonp.

Preventing malicious external scripts

I'm currently developing a game using PHP and MySql.
I'd like to allow users to be able to show images using a BBCode parser (NBBC) but i've been made aware of a potential security problem.
Allow me to explain:
The user enters a URL into a textarea box using code such as [img]http://example.com/image1.png[/img]
The user can then edit image1.png on the external server into a server side script that stores the user information (ip ect) and so forth.
User uses information to do some potentially nasty stuff!
My question is, how do we prevent this from happening and protect the users details when detailing with external sources?
The obvious answer is to only allow uploads to your site, but in this case, that really doesn't seem too practical.
Appreciate any help!
Actually you can by changing
[img]http://example.com/image1.png[/img]
into something like:
<img src="http://yourserver/proxy.blah?url=example.com/image1.png" />
So that your proxy would load the image instead of the user.
You can't because to your script it will look like a genuine image and there is no way of detecting anything different.
Any body can use .htaccess/ForceType to change the execution type of any file, grab user information and serve up an image in response.
I wrote a simple script for rotating images in a users forum signature many moons ago and it demonstrates this process: http://blog.simonholywell.com/post/374221718/flickering-images
You don't.
The only information the malicious user will be able to get is user's IP address and referrer URI, so you only need to make sure that nothing valuable is transmitted by it, (like session id, which you can bind to IP address or transfer via cookies).
It wouldn't even be necessary to turn that image into a script. The remote server's access log would capture the image request as it would any other request to a server. IP, browser UA, referer, etc...
If you allow external resources in user-provided data, you have no control whatsoever over how those resources are processed. If this image was for an Avatar (say), then nothing says the remote user can't make their avatar a puppy initially, then change it something nasty later on after the initial puppy picture's been approved.
Nothing says that the user couldn't point the avatar URL to a server they don't own themselves, in which case that other server's operator would get annoyed at the bandwidth theft and make the avatar picture into a Goatse-type image to get back at the bandwidth thief.
In short, if you allow external resources, you lose control. Keep everything in house where you can keep tabs on it.
Despite the responses saying this isn't a problem, it is. There are several ways to create a malicious image file that executes on the user's PC. You also have no control over whether the user's browser will honor the MIME type returned by the 3rd party server so it could return an executable file instead of an image, even though you may only allow links to files with image extensions (.png, .gif, .jpg, etc.). That interaction is entirely between your user and the 3rd party server but because it's embedded in your page the user experience will be that any infection originated from your site.
But even assuming the remote server only sends an image, you don't know if the image is even safe. See:
gifar image vulnerability
Infected .png files
Malicious code hides in jpgs
Uploading the images to your site is no walk in the park either, as discussed here.
User uses information to do some potentially nasty stuff!
You're being overly paranoid here. If a user is vulnerable just by having their IP known, their machine is already infested with a hundred different pieces of malware.

Does converting an image count as executing it

I'm talking about user uploaded images. These images might be unsafe and may even contain scripts and such. I was told that as long as I don't execute the image, I should be fine. What exactly counts as executing an image? If the user uploads a .png and I need to convert it to .jpg first before displaying it, does this conversion count as executing the image.
If you e.g. use some library to work with the library, then the only way for that to be a security risk is an issue with the library itself. E.g. if there is a buffer overflow security issue in the library, a mere process of reading the image could potentially make it execute the code conveniently hidden in the image (i.e. image would not be the image anymore, it will be turned into code).
If you use standard libraries, chances for such security holes are rather slim. Not zero, though, but I guess you would have to live either with that or not looking at any digital picture in your life again.
Provided that the tool used to convert the image isn't vulnerable to any exploits, the act of converting it does not involve executing it.
You can trust the image conversion process if you like, but as others have said, the risk exists that simply processing the data could leave you vulnerable. You can take other steps to isolate the image processing step if it is critical.
You could put that step on a separate machine, so that a compromise doesn't put the malicious code on the server communicating with the public. You could also run that process as another user, so that an exploit would have to escalate privileges in order to compromise your service.

Can something "bad" happen via img src?

I know, I know, title is quite bad, but I'll try to explain what I mean here. So, I ask my members to show their photos. They upload it somewhere, then paste their photos' URL into input and I save it to my database (MYSQL). Then, the photo is being seen on their profiles. I get the URL from database and do something like that: <img src="<?=$photo;?>" height="123px" width="123px">"> where $photo is URL taken from MYSQL. Is it totally safe? Can somebody upload for example .php file and harm my website? Do I need to check if URL's ending is .gif, .png, .jpg?
Thank you.
Edit: Yeah, of course I would protect my website from SQL injections and XSS attacks. But is there any way to harm my website in other way?
What you described may be vulnerable to an XSS (Cross-site Scripting) attack. Essentially, a nefarious user may be able to inject javascript code that could do bad things, while executing as your site.
For an example of this attack vector, check out: http://jarlsberg.appspot.com/part2#2__stored_xss_via_html_attribute
EDIT: It sounds like you are already protecting yourself agains SQL injections and XSS, and you are wondering if there is some way for someone to inject PHP code into your site. I don't think this is possible, since your server-side code will not be executing this string. You are simply instructing the client browser to download an image from a URL.
It may be possible for someone to link to an image file that is infected with a virus, which would then infect other visitors to your site, but it would not affect the site itself.
No, it's not safe at all, XSS attacks can be executed through image tags.
A simple example would be:
<IMG SRC=j&#X41vascript:alert('test2')>
http://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29
One thing you should consider - I could link you my "XUltra highres" image with about 200 megs. I guess this could break the loading experience of your site (depending on the design).
So beside "script attacks" is allowing users to link content into your site always problematic.
A couple of things to do are to validate that it is a real image in an accepted format (tpyically jpg,png and gif), and sanitize and change the filename.
You can use the PHP getimagesize function to check if it's a valid picture, and which format. You receive the alleged MIME type when the file is uploaded, but that is useless for validation. So, the following should work as the getimagesize function also validates images and returns the exif type.
$image_info=getimagesize($tempname);
$allowed_types=array(IMAGETYPE_PNG,IMAGETYPE_JPEG,IMAGETYPE_GIF);//these are actually the integers 1, 2 and 3
if(in_array($image_info[2],$allowed_types)){
//image is a valid image. You can also check the height and width.
}
In your upload processing, giving your file a new unique name that you have chosen is a good idea, and then you don't have to worry about them doing anything strange with the filename.
Edit:
I noticed you are referring to users supplying a URL to an image.
The answer I gave related to accepting, storing and displaying images users upload to your server.
The same principles apply, though, for displaying a URL of an image. You can get the image via cURL or fopen, save it to a temp file, and then check if it's really an image as described above. This can also catch the user linking to a non-existant or invalid image, so you could warn them. Also, enforce a filesize/dimension limit - you don't want someone linking to a 5 GB picture in their profile (though it would be their own bandwidth problem) as that could inconvenience your other users. The user could always change the file to something else later on, though. You could check once every x hours and warn people who are doing something suspicious, but that seems like a lot of effort on your end.
You can also enforce file name rules, say no unicode in file names, and the name must not include <>''""# -, which are characters that are rarely in legitimate image URLs.
Assuming you're already sanitizing for SQL injection. You need to prevent the user from doing something like this:
<img src="http://usmilitary/launchAllNukes?When=Now" />
or:
<img src""<script>//Evil code</script>" height="123px" width="123px" />
There's no point in checking the file extension, as that doesn't guarantee it's not processed by a script. GET requests (as used by img src) should be safe, and should not cause a major state change (e.g. purchase, delete user, etc.). However, there are buggy sites that do so.
Thus, the safest solution is to require users to upload the image to your site. If you do allow remote images, you should at least require the http or https scheme.
Before inserting into the db, use imagemagik to validate that the photo is a real image, not something else, and you should be OK.
If you allow users to specify any URL as a profile image, an attacker could exploit that to facilitate a denial of service attack against a smaller website. Its impact to the targeted website is equivalent to being slashdotted. For example, an attacker could change his/her profile picture URL to a large resource hosted on the targeted website. Each time a visitor to your site sees the attacker's profile, the targeted website wastes bandwidth serving the resource to the visitor.
A solution to this would be to only allow profile picture URLs that link to image hosting sites.
Strictly speaking - yes. I can post an image in your site that is hosted by my server.
<img alt="Kobi's Photo" src="http://example.com/photo.jpg" />
Seems innocent enough, but in fact, every visitor in your site, watching my image, can be tracked and recorded. Every visitor will get a session in my server, and and can even be given a cookie (not the fun kind). To make things even worse, I can track every page view of your visitors that displays my photo - the browser sends each url where the photo is display via the referer header.
By letting people hosting their own photos, you give away some privacy of your visitors.
Besides what the others have said regarding nefarious intentions, the only other issue I can see is if the image is of something really horrible, but then that can happen on any website where you can upload images.
If you actually allow the users to upload images, you can check the mime type (PHP's getimagesize() function can give you this information). This is not bulletproof either, but better than just checking the extension.
By uploading "somewhere", will you be hosting the files on your webserver?
There are lots of potential issues:
<img src="http://hacker.ru/badtimes.php" />
<img src="javascript:alert(String.fromCharCode(88,83,83))" />
Plus, specially-crafted jpgs can infect users machines:
http://www.microsoft.com/technet/security/bulletin/ms04-028.mspx
You could use a regular expression to filter the url in the PHP. That way you could prevent javascript tags being called and specify the valid file extensions.

What file types/extensions would you allow in for a document management application?

I am working on a kinda document management system. The end users are business class users.
I currently check and allow files to be uploaded only if they are one of the followings:
"png|jpe?g|gif|xls|doc|docx|csv|ppt|txt|pdf|rtf"
my questions are -
If I add "xml" into the list? can they cause any security issue?
What other document types/extensions I can add into this?
Or
Should I check NOT IN "exe|bat|php|js" and allow all other types?
Thanks for suggestions.
Should I check NOT IN "exe|bat|php|js" and allow all other types?
No. Whitelisting is better than blacklisting. There are many, many more dangerous filetypes than you are likely to know about. Those four barely scratch the surface.
If I add "xml" into the list? can they cause any security issue?
Yes it can, [X][HT]ML may contain scripting which operates in the security context of the site that served it. Which allows anyone who can upload documents to your site to inject JavaScript into your site (stealing cookies, request forgery etc).
However... it doesn't actually add any security issue you don't already have. Because even whitelisting by filetype/extension is not secure, thanks to IE and its misbegotten type-sniffing. You can upload a .txt file, and serve it correctly using the Content-Type: text/plain header, but if it contains sequences that IE thinks look like HTML, IE will ignore you and render it as HTML — boom, XSS.
(The same is true of any other type really, but .txt is the most openly vulnerable.)
There are two approaches to fixing this mess:
serve all user-uploaded files from a different hostname to the main application site, so that they are in different JS security contexts and do not share cookies or authentication data.
serve all user-uploaded files with the Content-Disposition: attachment header so that they will always be downloaded and not displayed within the browser.
(2) on its own should be watertight, but in practice in the past there have been ways around it due to browser and plugin exploits, so I'm not sure I'd completely trust in it. (1) on its own stops XSS, but it doesn't stop other nasties like HTML files containing iframes to exploit sites.
So it's best to do both.
Don't forget the rest of the new MS Office formats, xlsx, pptx and similar files.
As for security risk, it depends on where/how these files will be accessed. From a document management standpoint, XML wouldn't be something that I would assume by default, but I could see it needed.
I wouldn't do a wildcard exclude list, unless you are protecting the serving of the content.
Add the new MS Office doc extensions and the open office docs and you probably are good to go.
Perhaps adding Zip/Rar archives is an option too but you should consider restricting direct access to the files then.
Perhaps adding a clear message and link that new document types can de added upon request might help too?

Categories