New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Malicious hand-crafted PNG can be used to trigger DOS attack #2727
Comments
Are you sure there is the allocation? That error is explicitly thrown because we are preventing the allocation as it exceeds the configurable threshold. You can configure your own limits. https://docs.sixlabors.com/articles/imagesharp/security.html CC @antonfirsov |
There's a large initial allocation when creating the |
Ah good point. So rather than try to limit the image dimensions, I could instead pick a reasonable memory allocation limit, which would have stopped the image load before it allocated ~1.6GB and then spun for a really long time reading 500M scan lines of data. |
With that said, even if I set that limit considerably lower (say low enough to just barely support a 4K UHD image - 3840x2160), this specific attack would still be dangerous. The attacker could change their hand-crafted PNG to specify that the image is 8M pixels tall rather than 500M as the current attack did, which would then fit inside my more aggressive memory allocation limit (since it's only a single pixel wide). And then trying to load the image would again result in the CPU spinning for a really long time as it reads in 8M scan lines. It still feels like having an extra configuration option that lets you specify a limit on image dimensions would be a good safe-guard here. |
Why not read the ImageInfo first? You can do that without allocating and reject anything too large. The reason we use a memory limit instead of a dimensional limit is because images of pixel formats use different memory amounts. A single property is far easier to manage. |
We're using the |
Actually, looking at that code a bit more, I think I could squeeze an ImageInfo check into the |
If you are using Web how are the users uploading the image to make the request? You should control input there. Are you also using HMAC to protect the actual requests? |
Raw source images are uploaded into our system through a separate service, and then requests are sent from clients to the ImageSharp-based service to obtain permutations of those images (eg: resized to various smaller dimensions, cropped to a square aspect ratio, etc). We have numerous layers of defense to try and prevent malicious users from injecting bad content into our system, but it is a constant game of cat-and-mouse and every security barrier we erect is eventually surmounted by hackers. We fundamentally do not have a way to 100% trust the clients and so I'd like to try and have the ImageSharp-based service be as robust as possible in the face of potentially malicious content making it past our filters.
No, although we already have defenses in place to sanitize and reject image transformation query params that are outside the bounds of what we expect and can handle (as our servers are continuously being hit with automated fuzz attacks as well as hackers trying to manually manipulate the URLs to see what they can accomplish). |
This is where I would be inspecting those inputs and rejecting invalid ones. |
Yep that's a fair point. We weren't currently using ImageSharp to parse/inspect content as it was being uploaded into our system (it was only being used on the consumption side), but I think we've reached a point where that is the next necessary defense. Thank you for your feedback (and suggestion to customize the |
Ah yeah, when pushing for The nature of PNG is that small, low-entropy files can expand to a much (~30000x) bigger area in memory compared to the input size while also consuming noticeble amount of CPU% to fill that memory with content. This means that even if you run
I'm curious about the list of mechanisms you end up applying to secure your ImageSharp(.Web) usage. https://docs.sixlabors.com/articles/imagesharp/security.html feels like a chunk in it's current form, it would be nice to extend it with further (and more specific) recommendations. Keep us in the loop if you have the time! |
On the consumption side, the only thing we've done is add a simple sanitization pass on the query parameters in order to reject requests that don't tightly conform to expectations. Our server only supports a limited set of transformations with the sole purpose being to leverage client-side knowledge of how the requested image will be displayed in order to optimize bandwidth (ie: resizing to various smaller resolutions, cropping to a square aspect ratio, etc). The external clients come in multiple forms: a game that runs on PCs/game-consoles/phones/VR-headsets/etc, public facing websites, and internal admin tools/websites. All traffic routes through a CDN, with the ImageSharp service acting as the origin behind that CDN. The upload side has a more defenses, requiring user authentication from a valid game client (hackers use tools to extract a transient authentication token from RAM on the game client and then impersonate the game client) and a custom HTTP request signing algorithm (which hackers reverse engineered from game client binaries). We've also been building up a library of content validation filters that inspect the contents of the uploaded files before allowing them into the system. Per this discussion, I will likely be beefing up those validation filters to do more parsing & validation of images. |
Within the PNG decoder. we reuse the same scanline buffer when assigning pixel values and also limit temp buffer allocations used when inflating the compressed IDAT chunk. You were absolutely correct to push a memory limit over dimensional. I'm not convinced we have anything to action here. We provide configurable limits and the means to inspect image data before decoding. That's as much if not more than any other library. |
Prerequisites
DEBUG
andRELEASE
modeImageSharp version
3.1.4
Other ImageSharp packages and versions
ImageSharp.Web 3.1.2
Environment (Operating system, version and so on)
Azure App Service (Windows)
.NET Framework version
7.0
Description
A malicious user uploaded the attached image into our system. The PNG header specifies that the image is 1 pixel wide by 500M pixels tall. Attempting to load that image results in massive memory allocations and CPU load, and if the load actually succeeds without bringing down the server, subsequent operations such as resizing result in an
InvalidMemoryOperationException
as it attempts to allocate multiple GB of memory:Ideally loading this image (and others like it) would fail fast and treat it as a malformed image. Another possible option could be to have a configuration setting to specify the maximum allowable image dimensions that could then then be checked and validated during image loading so that the load could abort when faced with such a ridiculously large image.
Steps to Reproduce
Simply call
Image.Load()
referencing the attached PNG file.Images
The text was updated successfully, but these errors were encountered: