Imagesharp: Images with Polyglot attacks cause Access Violation Exception

Created on 30 May 2019  路  8Comments  路  Source: SixLabors/ImageSharp

Prerequisites

  • [x] I have written a descriptive issue title
  • [x] I have verified that I am running the latest version of ImageSharp
  • [x] I have verified if the problem exist in both DEBUG and RELEASE mode
  • [x] I have searched open and closed issues to ensure it has not already been reported

Description

When attempting to load a JPEG with a polyglot attack Image.Load throws an AccessViolationException. I've tried uploading the images directly but they appear to be cleaned - Images can be found here as well as some further examples on the previous link

_This also stops the image reading after a given point in latest NuGet package (1.0.0-beta0006).
You also get some really interesting side effects by evaluating frame.GetPixelSpan().Slice(1390000, 5) and $"{frame.GetPixelSpan()[1390000]" whilst in Debug_

Steps to Reproduce

Call Image.Load on attached files

System Configuration

  • ImageSharp version: SixLabors.ImageSharp.1.0.0-dev002709
  • Other ImageSharp packages and versions: SixLabors.Core.1.0.0-dev000108
  • Environment (Operating system, version and so on): OS X 10,13.2
  • .NET Framework version: core 3 preview 5
  • Additional information:
jpeg

All 8 comments

Thanks for reporting this @sport-monkey we really appreciate it!

I'll take a look at this myself as I've already done the fuzz fixes for jpeg so I have a hunch where the issue will be

I'm not seeing this with 1.0.0-dev002715 on my Windows machine using NET Core 2.1 or Net Framework 4.6.2, 4.7.2

I've added the source code I use to run this, if I change the proj to target 2.1 it prints (1), if I use the 3.0 we get. (Net Core 2.1 on Win 10 x64)

C:\Users\User\ImageSharp>dotnet run
1
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.HuffmanScanDecoder.DecodeBlockBaseline(SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.JpegComponent, SixLabors.ImageSharp.Formats.Jpeg.Components.Block8x8 ByRef, SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.HuffmanTable ByRef, SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.HuffmanTable ByRef)
   at SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.HuffmanScanDecoder.ParseBaselineDataInterleaved()
   at SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.HuffmanScanDecoder.ParseEntropyCodedData()
   at SixLabors.ImageSharp.Formats.Jpeg.JpegDecoderCore.ProcessStartOfScanMarker()
   at SixLabors.ImageSharp.Formats.Jpeg.JpegDecoderCore.ParseStream(System.IO.Stream, Boolean)
   at SixLabors.ImageSharp.Formats.Jpeg.JpegDecoderCore.Decode[[SixLabors.ImageSharp.PixelFormats.Rgba32, SixLabors.ImageSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]](System.IO.Stream)
   at SixLabors.ImageSharp.Formats.Jpeg.JpegDecoder.Decode[[SixLabors.ImageSharp.PixelFormats.Rgba32, SixLabors.ImageSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]](SixLabors.ImageSharp.Configuration, System.IO.Stream)
   at SixLabors.ImageSharp.Image.Decode(System.IO.Stream, SixLabors.ImageSharp.Configuration)
   at SixLabors.ImageSharp.Image.WithSeekableStream[[System.ValueTuple`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](SixLabors.ImageSharp.Configuration, System.IO.Stream, System.Func`2<System.IO.Stream,System.ValueTuple`2<System.__Canon,System.__Canon>>)
   at SixLabors.ImageSharp.Image.Load(SixLabors.ImageSharp.Configuration, System.IO.Stream, SixLabors.ImageSharp.Formats.IImageFormat ByRef)
   at SixLabors.ImageSharp.Image.Load(SixLabors.ImageSharp.Configuration, System.String, SixLabors.ImageSharp.Formats.IImageFormat ByRef)
   at SixLabors.ImageSharp.Image.Load(System.String)
   at ImageSharp.Program.Main(System.String[])

Ok. This looks like something we should be raising upstream on the CoreFX repo. Would you please do that and we鈥檒l see what we can all work out together. Thanks!

Can the value in r cause the i read of zigzag to go out of bounds (as the indexer is not bounds checked)?

https://github.com/SixLabors/ImageSharp/blob/2fcba54a3e134bc04f0218fe9e8b4af7b700c20a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs#L455-L457

@benaadams Looks like you might be onto something here.

Running the following code. I can throw an IndexOutOfRangeException when h is 49.

``` c#
void Main()
{
byte[] zigzag =
{
0,
1, 8,
16, 9, 2,
3, 10, 17, 24,
32, 25, 18, 11, 4,
5, 12, 19, 26, 33, 40,
48, 41, 34, 27, 20, 13, 6,
7, 14, 21, 28, 35, 42, 49, 56,
57, 50, 43, 36, 29, 22, 15,
23, 30, 37, 44, 51, 58,
59, 52, 45, 38, 31,
39, 46, 53, 60,
61, 54, 47,
55, 62,
63
};

var block = new short[64];

// s is read from a table of bytes 
for (int h = 0; h < 255; h++)
{
    for (int i = 1; i < 64; i++)
    {
        int s = h;
        int r = s >> 4;
        s &= 15;

        if (s != 0)
        {
            i += r;
            // Ignore Extend
            block[zigzag[i++]] = (short)s;
        }
        else
        {
            if (r == 0)
            {
                break;
            }

            i += 16;
        }
    }
}

}
```

However, look what libjpeg-turbo do. They pad out the zigzag array to handle such corrupted data.

libjpeg zigzag data

If I use their extended table then no exception is thrown.

@sport-monkey is the issue reproducible with this smaller image as well?

@sport-monkey is the issue reproducible with this smaller image as well?

@antonfirsov I've just tried, it's not reproducible with that image.

Was this page helpful?
0 / 5 - 0 ratings