Repository navigation
Payloads that caused a DOS attack (GIF / JPEG) #2758
Description
Activity
Hello @ErazerBrecht, thank you for this.
Upon reviewing the issues, I was unable to open the folder containing a copy of your repository on my Windows 11 machine, as File Explorer would instantly crash. It's unclear how you were able to view the output there.
However, I was able to conduct an investigation on an older MacBook.
Regarding the GIF issue, I have opened a pull request which has been successfully tested against your image. It's important to note that your test code has a memory leak due to not disposing of images after allocation.
For the JPEG issue, the
DividebyZeroExceptionyou mentioned is unclear to me. The encoder in your sample code seems to replicate the default encoder options, and since the encoder only encodes the decoded pixel buffer, the input appears to be irrelevant. Further clarification is needed on this matter.The increase in JPEG encoded output size is to be expected. The images provided have been modified to specify large dimensions, such as 59787x511 pixels. These dimensions are taken from the jpeg header, and we attempt to decode to a buffer that matches these dimensions. Consequently, when encoding, we are working with a pixel buffer that reflects the full manipulated dimensions, resulting in the encoding of a significantly larger amount of data.
Reacted by Brecht CarlierHey @JimBobSquarePants
Already thanks for taking a look at this.Yeah I can just use the file explorer on Windows 11.
Here are the payloads in a ZIP so hopefully that works.funnyanim.gif.zip
funnyjpegs.zipWhat I mean is that if I swap this part of the code:
using var output = new MemoryStream(); var encoder = new JpegEncoder { Quality = 75 }; image.Save(output, encoder); Console.WriteLine($"Input: {input.Length} vs Output: {output.Length}");To this:
using var output = new MemoryStream(); var encoder = new JpegEncoder(); image.Save(output, encoder); Console.WriteLine($"Input: {input.Length} vs Output: {output.Length}");Than it throws the exception:
Unhandled exception. System.DivideByZeroException: Attempted to divide by zero. at SixLabors.ImageSharp.Formats.Jpeg.JpegEncoderCore.WriteDefineQuantizationTables(JpegQuantizationTableConfig[] configs, Nullable`1 optionsQuality, JpegMetadata metadata, Span`1 tmpBuffer) at SixLabors.ImageSharp.Formats.Jpeg.JpegEncoderCore.Encode[TPixel](Image`1 image, Stream stream, CancellationToken cancellationToken) at SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder.Encode[TPixel](Image`1 image, Stream stream, CancellationToken cancellationToken) at SixLabors.ImageSharp.Formats.ImageEncoder.EncodeWithSeekableStream[TPixel](Image`1 image, Stream stream, CancellationToken cancellationToken) at SixLabors.ImageSharp.Formats.ImageEncoder.Encode[TPixel](Image`1 image, Stream stream) at SixLabors.ImageSharp.Image.EncodeVisitor.Visit[TPixel](Image`1 image) at SixLabors.ImageSharp.Image`1.Accept(IImageVisitor visitor) at SixLabors.ImageSharp.Advanced.AdvancedImageExtensions.AcceptVisitor(Image source, IImageVisitor visitor) at SixLabors.ImageSharp.Image.Save(Stream stream, IImageEncoder encoder) at Program.<<Main>$>g__SaveLoadImage|0_0(String fileName) in I:\POC\ImageSharp.Payloads\ImageSharp.Payloads.Jpeg\Program.cs:line 32 at Program.<Main>$(String[] args) in I:\POC\ImageSharp.Payloads\ImageSharp.Payloads.Jpeg\Program.cs:line 14For me the exception is better since it prevents a malicious actor of uploading the file.
We fixed it in our own code by checking if the output ImageSharp is 10x bigger than the input, if this is the case we don't allow the image (only if the result is bigger than x amount of Mb).Reacted by James Jackson-SouthThanks for the update @ErazerBrecht I think understand what must be happening with the jpeg encoder now.
You can see the progress of the PR here #2759
I've solved the GIF problem by refactoring the LZW decoder to work line by line. This limits allocations for the index buffer to 64K preventing the massive allocation you were seeing.
I'll have a look at the JPEG issue in the morning. I believe my inability to view the images in your repository has something to do with my usage of the new dev drive. I can see them in my standard drive.
P.S you can use the
Image.Identify(...)methods to determine the decoded dimensions of an image and also configure memory allocation limitations which will throw exceptions when exceeded.- linked a pull request that will close this issuev3.1.x Fix 2758 #2759
on Jun 28, 2024 @ErazerBrecht I've added a fix for the
DividebyZeroExceptionto the PR. There are no fixes for the output file size since that is simply how large a true encoded JPEG for those dimensions would be. This is how any library that can open the images would behave.Reacted by Tieson TrowbridgeReacted by Niels Hofmans- added and removed
on Jun 28, 2024 Fixed with 3.1.5
Reacted by Niels Hofmans
Prerequisites
DEBUGandRELEASEmodeImageSharp version
3.1.4
Other ImageSharp packages and versions
Environment (Operating system, version and so on)
Windows 11
Alpine 3.19
.NET Framework version
.NET 8
Description
Hello,
GIF
When using a certain GIF we are seeing OOM's.
When debugging this locally I allocate +- 20Gb when handling that specific payload 5 times in parallel.
Payload: https://github.com/ErazerBrecht/ImageSharp.Payloads/blob/master/ImageSharp.Payloads.Gif/funnyanim.gif
Source code: https://github.com/ErazerBrecht/ImageSharp.Payloads/blob/master/ImageSharp.Payloads.Gif/Program.cs
When changing the source code to use the 'earth.gif' it works as intended and there is no spike in memory allocation.
JPEG
We have some payloads that cause resource amplification. There are very small <1460 bytes but when using Imagesharp they result into a very big result (biggest one goes to >40Mb). This only happens when specifying a quality level in the JPG encoder.
When not using one the payloads throw on a DividebyZeroException.
Payloads
https://github.com/ErazerBrecht/ImageSharp.Payloads/blob/master/ImageSharp.Payloads.Jpeg/83.jpg
https://github.com/ErazerBrecht/ImageSharp.Payloads/blob/master/ImageSharp.Payloads.Jpeg/92.jpg
https://github.com/ErazerBrecht/ImageSharp.Payloads/blob/master/ImageSharp.Payloads.Jpeg/93.jpg
Source code: https://github.com/ErazerBrecht/ImageSharp.Payloads/blob/master/ImageSharp.Payloads.Jpeg/Program.cs
Payloads were created by: https://app.intigriti.com/profile/whatevicanhaz
Sincerely,
Brecht
Steps to Reproduce
See:
https://github.com/ErazerBrecht/ImageSharp.Payloads
Images
No response