Fuzzing ImageMagick and Digging Deeper into CVE-2020-27829

0
85

[ad_1]

Introduction:
ImageMagick is a massively well-liked open supply software program that’s utilized in lot of techniques world wide. It’s obtainable for the Home windows, Linux, MacOS platforms in addition to Android and iOS. It’s used for modifying, creating or changing numerous digital picture codecs and helps numerous codecs like PNG, JPEG, WEBP, TIFF, HEIC and PDF, amongst others.
Google OSS Fuzz and different menace researchers have made ImageMagick the frequent focus of fuzzing, a particularly well-liked method utilized by safety researchers to find potential zero-day vulnerabilities in open, in addition to closed supply software program. This analysis has resulted in numerous vulnerability discoveries that should be addressed regularly by its maintainers. Regardless of the efforts of many to show such vulnerabilities, current fuzzing analysis from McAfee has uncovered new vulnerabilities involving processing of a number of picture codecs, in numerous open supply and closed supply software program and libraries together with ImageMagick and Home windows GDI+.
Fuzzing ImageMagick:
Fuzzing open supply libraries has been coated in an in depth weblog “Vulnerability Discovery in Open Supply Libraries Half 1: Instruments of the Commerce” final yr. Fuzzing ImageMagick may be very properly documented, so we can be rapidly masking the method on this weblog put up and can deal with the foundation trigger evaluation of the problem now we have discovered.
Compiling ImageMagick with AFL:
ImageMagick has lot of configuration choices which we are able to see by working following command:

We will customise numerous parameters as per our wants. To compile and set up ImageMagick with AFL for our case, we are able to use following instructions:

$CC=afl-gcc CXX=afl=g++ CFLAGS=”-ggdb -O0 -fsanitize=handle,undefined -fno-omit-frame-pointer” LDFLAGS=”-ggdb -fsanitize=handle,undefined -fno-omit-frame-pointer” ./configure
$ make -j$(nproc)
$sudo make set up

This can compile and set up ImageMagick with AFL instrumentation. The binary we can be fuzzing is “magick”, also called “magick device”. It has numerous choices, however we can be utilizing its picture conversion characteristic to transform our picture from one format to a different.
A easy command could be embrace the next:

$ magick <enter file> <output file>

This command will convert an enter file to an output file format. We can be fuzzing this with AFL.
Gathering Corpus:
Earlier than we begin fuzzing, we have to have a very good enter corpus. A technique of amassing corpus is to go looking on Google or GitHub. We will additionally use present check corpus from numerous software program. A very good check corpus is obtainable on the  AFL web site right here: https://lcamtuf.coredump.cx/afl/demo/
Minimizing Corpus:
Corpus assortment is one factor, however we additionally want to attenuate the corpus. The way in which AFL works is that it’ll instrument every fundamental block in order that it might probably hint this system execution path. It maintains a shared reminiscence as a bitmap and it makes use of an algorithm to test new block hits. If a brand new block hit has been discovered, it would save this data to bitmap.
Now it might be doable that multiple enter file from the corpus can set off the identical path, as now we have collected pattern information from numerous sources, we don’t have any data on what paths they may set off on the runtime. If we use this corpus with out eradicating such information, then we find yourself losing time and CPU cycles. We have to keep away from that.
Curiously AFL provides a utility referred to as “afl-cmin” which we are able to use to attenuate our check corpus. It is a advisable factor to do earlier than you begin any fuzzing marketing campaign. We will run this as follows:

$afl-cmin -i <enter listing> -o <output listing> — magick @@ /dev/null

This command will decrease the enter corpus and can maintain solely these information which set off distinctive paths.
Operating Fuzzers:
After now we have minimized corpus, we are able to begin fuzzing. To fuzz we have to use following command:

$afl-fuzz -i <mincorpus listing> -o <output listing> — magick @@ /dev/null

This can solely run a single occasion of AFL using a single core. In case now we have multicore processors, we are able to run a number of situations of AFL, with one Grasp and n variety of Slaves. The place n is the obtainable CPU cores.
To test obtainable CPU cores, we are able to use this command:

This can give us the variety of CPU cores (relying on the system) as follows:

On this case there are eight cores. So, we are able to run one Grasp and as much as seven Slaves.
To run grasp situations, we are able to use following command:

$afl-fuzz -M Grasp -i <mincorpus listing> -o <output listing> — magick @@ /dev/null

We will run slave situations utilizing following command:

$afl-fuzz -S Slave1 -i <mincorpus listing> -o <output listing> — magick @@ /dev/null
$afl-fuzz -S Slave2 -i <mincorpus listing> -o <output listing> — magick @@ /dev/null

The identical could be carried out for every slave. We simply want to make use of an argument -S and might use any identify like slave1, slave2, and so on.

Outcomes:
Inside just a few hours of starting this Fuzzing marketing campaign, we discovered one crash associated to an out of certain learn inside a heap reminiscence. Now we have reported this subject to ImageMagick, they usually had been very immediate in fixing it with a patch the very subsequent day. ImageMagick has launch a brand new construct with model: 7.0.46 to repair this subject. This subject was assigned CVE-2020-27829.
Analyzing CVE-2020-27829:
On checking the POC file, we discovered that it was a TIFF file.

After we open this file with ImageMagick with following command:

$magick poc.tif /dev/null

In consequence, we see a crash like beneath:

As is obvious from the above log, this system was attempting to learn 1 byte previous allotted heap buffer and subsequently ASAN prompted this crash. This could atleast result in a  ImageMagick crash on the techniques working weak model of ImageMagick.
Understanding TIFF file format:
Earlier than we begin debugging this subject to discover a root trigger, it’s crucial to know the TIFF file format. Its specification may be very properly described right here: http://paulbourke.web/dataformats/tiff/tiff_summary.pdf.
In brief, a TIFF file has three elements:

Picture File Header (IFH) – Accommodates data similar to file identifier, model, offset of IFD.
Picture File Listing (IFD) – Accommodates data on the peak, width, and depth of the picture, the variety of color planes, and so on. It additionally comprises numerous TAGs like colormap, web page quantity, BitPerSample, FillOrder,
Bitmap information – Accommodates numerous picture information like strips, tiles, and so on.

We will tiffinfo utility from libtiff to collect numerous details about the POC file. This permits us to see the next data with tiffinfo like width, top, pattern per pixel, row per strip and so on.:

There are some things to notice right here:

TIFF Dir offset is: 0xa0
Picture width is: 3 and size is: 32
Bits per pattern is: 9
Pattern per pixel is: 3
Rows per strip is: 1024
Planer configuration is: single picture aircraft.
We can be utilizing this information shifting ahead on this put up.

Debugging the problem:
As we are able to see within the crash log, program was crashing at perform “PushQuantumPixel” within the following location in quantum-import.c line 256:

On checking “PushQuantumPixel” perform in “MagickCore/quantum-import.c” we are able to see the next code at line #256 the place program is crashing:

We will see following:

“pixels” appears to be a personality array
inside a for loop its worth is being learn and it’s being assigned to quantum_info->state.pixel
its handle is elevated by one in every loop iteration

This system is crashing at this location whereas studying the worth of “pixels” which implies that worth is out of certain from the allotted heap reminiscence.
Now we have to determine following:

What’s “pixels” and what information it comprises?
Why it’s crashing?
How this was mounted?

Discovering root trigger:
To begin with, we are able to test “ReadTIFFImage” perform in coders/tiff.c file and see that it allocates reminiscence utilizing a “AcquireQuantumMemory” perform name, which seems as per the documentation talked about right here:
https://imagemagick.org/api/reminiscence.php:
“Returns a pointer to a block of reminiscence no less than rely * quantum bytes suitably aligned for any use.
The format of the “AcquireQuantumMemory” methodology is:
void *AcquireQuantumMemory(const size_t rely,const size_t quantum)
An outline of every parameter follows:
rely
the variety of objects to allocate contiguously.
quantum
the scale (in bytes) of every object. “
On this case two parameters handed to this perform are “extent” and “sizeof(*strip_pixels)”

We will see that “extent” is calculated as following within the code beneath:

There’s a perform TIFFStripSize(tiff) which returns measurement for a strip of information as talked about in libtiff documentation right here:
http://www.libtiff.org/man/TIFFstrip.3t.html
In our case, it returns 224 and we are able to additionally see that within the code talked about above,  “image->columns * sizeof(uint64)” can also be added to extent, which ends up in 24 added to extent, so extent worth turns into 248.
So, this extent worth of 248 and sizeof(*strip_pixels) which is 1 is handed to “AcquireQuantumMemory” perform and whole reminiscence of 248 bytes get allotted.
That is how reminiscence is allotted.

“Strip_pixel” is pointer to newly allotted reminiscence.

Observe that that is 248 bytes of newly allotted reminiscence. Since we’re utilizing ASAN, every byte will comprise “0xbe” which is default for newly allotted reminiscence by ASAN:
https://github.com/llvm-mirror/compiler-rt/blob/grasp/lib/asan/asan_flags.inc

The reminiscence begin location is 0x6110000002c0 and the tip location is 0x6110000003b7, which is 248 bytes whole.

This reminiscence is ready to 0 by a “memset” name and that is assigned to a variable “p”, as talked about in beneath picture. Please additionally observe that “p” can be used as a pointer to traverse this reminiscence location going ahead in this system:

Afterward we see that there’s a name to “TIFFReadEncodedPixels” which reads strip information from TIFF file and shops it into newly allotted buffer “strip_pixels” of 248 bytes (documentation right here: http://www.libtiff.org/man/TIFFReadEncodedStrip.3t.html):

To know what this TIFF file information is, we have to once more discuss with TIFF file construction. We will see that there’s a tag referred to as “StripOffsets” and its worth is 8, which specifies the offset of strip information inside TIFF file:

We see the next after we test information at offset 8 within the TIFF file:

We see the next after we print the info in “strip_pixels” (observe that it’s in little endian format):

So “strip_pixels” is the precise information from the TIFF file from offset 8. This can be traversed by means of pointer “p”.
Inside “ReadTIFFImage” perform there are two nested for loops.

The primary “for loop” is liable for iterating for “samples_per_pixel” time which is 3.
The second “for loop” is liable for iterating the pixel information for “image->rows” instances, which is 32. This second loop can be executed for 32 instances or variety of rows within the picture no matter allotted buffer measurement .
Inside this second for loop, we are able to see one thing like this:

We will discover that “ImportQuantumPixel” perform makes use of the “p” pointer to learn the info from “strip_pixels” and after every name to “ImportQuantumPixel”, worth of “p” can be elevated by “stride”.

Right here “stride” is calculated by calling perform “TIFFVStripSize()” perform which as per documentation returns the variety of bytes in a strip with nrows rows of information.  On this case it’s 14. So, each time pointer “p” is incremented by “14” or “0xE” contained in the second for loop.

If we print the picture construction which is handed to “ImportQuantumPixels” perform as parameter, we are able to see following:

Right here we are able to discover that the columns worth is 3, the rows worth is 32 and depth is 9. If we test within the POC TIFF file, this has been taken from ImageWidth and ImageLength and BitsPerSample worth:

Finally, management reaches to “ImportRGBQuantum” after which to the “PushQuantumPixel” perform and one of many arguments to this perform is the pixels information which is pointed by “p”. Do not forget that this factors to the reminiscence handle which was beforehand allotted utilizing the “AcquireQuantumMemory” perform, and that its size is 248 byte and each time worth of “p” is elevated by 14.
The “PushQuantumPixel” perform is used to learn pixel information from “p” into the inner pixel information storage of ImageMagick. There’s a for loop which is liable for studying information from the supplied pixels array of 248 bytes right into a construction “quantum_Info”. This loop reads information from pixels incrementally and saves it within the “quantum_info->state.pixels” subject.

The foundation trigger right here is that there are not any correct bounds checks and this system tries to learn information past the allotted buffer measurement on the heap, whereas studying the strip information inside a for loop.
This causes a crash in ImageMagick as we are able to see beneath:

Root trigger
Due to this fact, to summarize, this system crashes as a result of:

This system allocates 248 bytes of reminiscence to course of strip information for picture, a pointer “p” factors to this reminiscence.
Inside a for loop this pointer is elevated by “14” or “0xE” for variety of rows within the picture, which on this case is 32.
Based mostly on this calculation, 32*14=448 bytes or extra quantity of reminiscence is required however solely 248 in precise reminiscence had been allotted.
This system tries to learn information assuming whole reminiscence is of 448+ bytes, however the truth that solely 248 bytes can be found causes an Out of Certain reminiscence learn subject.

The way it was mounted?
If we test on the patch diff, we are able to see that the next modifications had been made to repair this subject:

Right here the 2nd argument to “AcquireQuantumMemory” is multiplied by 2 thus rising the full quantity of reminiscence and stopping this Out of Certain learn subject from heap reminiscence. The full reminiscence allotted is 496 bytes, 248*2=496 bytes, as we are able to see beneath:

One other subject with the repair:
A brand new model of ImageMagick 7.0.46 was launched to repair this subject. Whereas the patch fixes the reminiscence allocation subject, if we test the code beneath, we are able to see that there was a name to memset which didn’t set the correct reminiscence measurement to zero.

Reminiscence was allotted extent*2*sizeof(*strip_pixels) however on this memset to 0 was solely carried out for extent*sizeof(*strip_pixels). This implies half of the reminiscence was set to 0 and relaxation contained 0xbebebebe, which is by default for ASAN new reminiscence allocation.

This has since been mounted in subsequent releases of ImageMagick through the use of extent=2*TIFFStripSize(tiff); within the following patch:
https://github.com/ImageMagick/ImageMagick/commit/a5b64ccc422615264287028fe6bea8a131043b59#diff-0a5eef63b187504ff513056aa8fd6a7f5c1f57b6d2577a75cff428c0c7530978
Conclusion:
Processing numerous picture information requires deep understanding of assorted file codecs and thus it’s doable that one thing might not be precisely applied or missed. This could result in numerous vulnerabilities in such picture processing software program. A few of this vulnerability can result in DoS and a few can result in distant code execution affecting each set up of such well-liked software program.
Fuzzing performs an necessary position find vulnerabilities typically missed by builders and through testing. We at McAfee consistently fuzz numerous closed supply in addition to open supply software program to assist safe them. We work very carefully with numerous distributors and do accountable disclosure. This reveals McAfee’s dedication in direction of securing the software program and defending our clients from numerous threats.
We are going to proceed to fuzz numerous software program and work with distributors to assist mitigate danger arriving from such threats.
We want to thank and admire ImageMagick workforce for rapidly resolving this subject inside 24 hours and releasing a brand new model to repair this subject.
x3Cimg top=”1″ width=”1″ model=”show:none” src=”https://www.fb.com/tr?id=766537420057144&ev=PageView&noscript=1″ />x3C/noscript>’);

[ad_2]