What are the security considerations when a server fetches a file from an untrusted domain?
What are the security considerations when resizing an image that you don’t trust with PHPs GD2 library?
The file will be stored on the server machine, and will be offered for download. I know I can’t trust the MIME-Type header. Is there anything else I should be aware of?
I have a webservice that looks like this:
input
An http-URL (or a String that is expected to be a URL)
output
A meta description of the file, or an error if there was one.
The meta description has one of two forms:
- It’s an image + a URL to the image on my domain + a thumbnail of the image (generated on and hosted by my server)
- It’s not an image + a URL to the file on my domain
update
Concerns that I can come up with:
-
The remote server is a malicious server that will send tiny bits of information, enough to keep the socket open, but doesn’t do anything useful – like slowloris. I don’t know how real of a threat this is. I suppose it could be easily avoided with timeout + progress check.
-
The remote server serves something that looks like an image (headers, mime-type) but causes PHP to crash when I load it with GD2.
-
The server sends a useless or bad MIME-type header. Like
text-plainfor binary files. -
The remote server serves an image with a virus in it. I assume that resizing the image will get rid of the virus, but I will serve the original image if there is no reason to scale.
-
The remote server serves a file with a virus in it. The file will not be treated as an image so my server will do nothing with it. Nothing will happen until the user downloads, and runs it.
Also, I assume I can trust the users of my service. This is a private application in a situation where users can be held accountable for bad behavior. I assume they wont intentionally try to break it.
The domain (host) and the file is not to be trusted. This spreads over two points:
To transport the data safely, use a timeout and a size limit. Modern HTTP client libraries offer both of that. If the file could not be requested in time, drop the connection. If the file is too large, drop the data. Tell the user that there was a problem getting the file. Alternatively let the user handle the transport to that server by using the users browser and javascript to obtain the file. Then post it. Set the post limit with your script.
As long as the data is untrusted you need to handle it with caution. That means, you implement yourself a process that is able to run different security checks on the file before you mark it as “safe”.
Do not pass untrusted data to the image library then. See the step above, bring it into a safe state first.
I think you’re still at the point above. How to come to safe from untrusted. Sure you can’t trust the Content-Type header, however it’s good to understand it as well.
You want to protect against the Unrestricted File Upload VulnerabilityOWASP.
All this depends a bit how much you want to do, but I think you get the idea. Create a process that works for you knowing where improvement can be added, but first create an infrastructure that is modular enough to deal with error-cases and which probably encapsulates the process enough to deal with any outcome.
You could delegate critical parts to a system that you don’t need to care about, e.g. to separate processing from hosting. Additionally, when you host the images the webserver must not be clever. The more stupid a system is, the less exploitable it is (normally).
If hosting is not part of your business, why not hand it over to amazon s3 or similar stores? Your domain can be preserved via DNS settings.
Keep the libraries you use to verify images with up-to-date (which implicates you know which libraries are used and their versio, e.g. the PHP exif extension is making use of mbstring etc. pp. – track the whole tree down). Take care you’re in the position to report flaws to the library maintainers in a useful way, e.g. with logging, storing upload data to reproduce stuff etc..
Get knowledge about which exploits for images did exist in the past and which systems/components/libraries (example, see disclaimer there) were affected.
Also get into the topic which are common ways to exploit something, to get the basics together (I’m sure you are aware, however it’s always good to re-read some stuff):
Some related questions, assorted: