oss-sec mailing list archives

Fwd: out-of-bounds read in MagickCore/property.c:1396 could lead to memory leak/ Integer overflow read to RCE


From: Ibrahim el-sayed <i.elsayed92 () gmail com>
Date: Thu, 23 Jun 2016 01:47:21 +0100

Hi Mitre CVE assignment team,
I have submitted the following two bugs to ImageMagick. Both got acknowledged and fixed in the following patch
https://github.com/ImageMagick/ImageMagick/commit/d8ab7f046587f2e9f734b687ba7e6e10147c294b 
<https://github.com/ImageMagick/ImageMagick/commit/d8ab7f046587f2e9f734b687ba7e6e10147c294b>
I would be so glad if you can issue me CVEs for them

Regards
Ibrahim



Begin forwarded message:

From: Ibrahim el-sayed <i.elsayed92 () gmail com>
Subject: Integer overflow that lead to RCE
Date: June 21, 2016 at 6:58:20 PM GMT+1
To: security () imagemagick org

Hi ImageMagick security team,
I was fuzzing imagemagick with AFL and I think I found an integer overflow that might lead to remote code execution.

The vulnerability exists in the following line
https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/profile.c#L2025 
<https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/profile.c#L2025>

components=(ssize_t) ReadProfileLong(endian,q+4);   << I think component should be size_t
number_bytes=(size_t) components*format_bytes[format];
I think components variable is upgraded to integer in this line.
component is stored in edx in the assembly and before the multplication the following instructions are executed

0000000000475D3E movsxd  rax, edx ;edx contains components variable and it is using movsx (move signed extended which 
I think the main cause of the vulnerability). if The value of components anything above 0xC0000000 the sign extension 
will be 1 and rax will be 0xFFFFFFFFC0000000. The main problem of this I think because ssize_t which covers the -1 
value
0000000000475D41 movsxd  rcx, ds:SyncExifProfile_format_bytes[rcx*4]
0000000000475D49 imul    rcx, rax
0000000000475D4D cmp     rcx, rax ;This is unsigned comparison because of jump below (jl)
0000000000475D50 jl      exit

After the multiplication rcx contains number_bytes as (integer 64bit) and not size_t

https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/profile.c#L2028 
<https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/profile.c#L2028>
In the if condition, the PoC takes the else part.

@ line https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/profile.c#L2036 
<https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/profile.c#L2036>

2036: if ((size_t) (offset+number_bytes) > length)
An integer oveflow occurs in this comparison because number_bytes is a very large number like (0xFFFFFFFFFFFFFF87) 
and when we add offset to it which we control we can overflow and the result is < length so we pass this if condition.

2040: p=(unsigned char *) (exif+offset);
At 2040 the offset value is the value we are controlling and can range between 0x7B-0x40000001 as illustrated in the 
PoC

pointer p is used later in to write data to it.
The PoC goes into the switch statement and then choose case 0x011b. And then it write 4 bytes on line
2052: (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
Needless to day we can control image->resolution.y
Also if we took another path in the switch statement we can also control
image->orientation or image->units which are the values written to the pointer we can control.


You can find attached two Proof of Concept files.
PoC1:
This PoC will set number_bytes = 0xFFFFFF87  ==>> will be sign extended to 0xFFFFFFFFFFFFFFFF87 and offset = 0x7B.
This PoC will basically write 4 null bytes into position exif+0x7B (offset)

PoC2:
This PoC will set number_bytes = 0xC0000000 which will be sign extended to 0xFFFFFFFFC0000000 and offset = 0x40000001
This will write 4 null bytes in position exif+0x40000001 (offset).

PoC2 will cause a seg-fault because usually this memory address (exif+0x40000001) might not be mapped or doesn't have 
the correct permission to write to


Regards
Ibrahim M. El-Sayed
Security Engineer
Website: https://www.ibrahim-elsayed.com <https://www.ibrahim-elsayed.com/>
@ibrahim_mosaad






Begin forwarded message:

From: Ibrahim el-sayed <i.elsayed92 () gmail com>
Subject: out-of-bounds read in MagickCore/property.c:1396 could lead to memory leak
Date: June 21, 2016 at 3:04:23 PM GMT+1
To: security () imagemagick org

Hi ImageMagick Security Team,

I think I have found a security bug. The bug was found while fuzzing ImageMagick with afl-fuzz

command: magick identify PoC.jpg
The vulnerability could lead to information leakage because the pointer is used later to read data from the memory


MagickCore/property.c:1401 format=(size_t) ReadPropertyUnsignedShort(endian,q+2);
MagickCore/property.c:1404 components=(ssize_t) ReadPropertySignedLong(endian,q+4);

The code basically reads the number of entries inside directory object in an image
MagickCore/property.c:1382 number_entries=(size_t) ReadPropertyUnsignedShort(endian,directory);

By manipulating bytes at position 0x76 and 0x77 in the PoC image, we can control number_entries variable which is 
used to in the loop. By controlling number_entries we can partially control q
MagickCore/property.c:1396 q=(unsigned char *) (directory+(12*entry)+2);

In the previous line we control the value of "entry". As a result, we can partially control q which can be used later 
to read arbitrary data from the process of ImageMagick.

PoC image: https://www.ibrahim-elsayed.com/uploads/PoC_imagemagick_1.jpg 
<https://www.ibrahim-elsayed.com/uploads/PoC_imagemagick_1.jpg>
[backtrace]
storm@storm ~/f/f/f/crashes> gdb -q magick core.magick.14585
Reading symbols from magick...done.
[New LWP 14585]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `magick identify PoC.jpg'.
Program terminated with signal SIGABRT, Aborted.
#0 0x00007f110bac6c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56    ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007f110bac6c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007f110baca028 in __GI_abort () at abort.c:89
#2 0x0000000000421b5b in MagickSignalHandler (signal_number=6) at MagickCore/magick.c:1310
#3 <signal handler called>
#4 0x00007f110bac6c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#5 0x00007f110baca028 in __GI_abort () at abort.c:89
#6 0x0000000000421b5b in MagickSignalHandler (signal_number=11) at MagickCore/magick.c:1310
#7 <signal handler called>
#8 ReadPropertySignedLong (buffer=0x293c000 <error: Cannot access memory at address 0x293c000>,
    endian=LSBEndian) at MagickCore/property.c:745
#9 GetEXIFProperty (image=image@entry=0x291aff0, property=property@entry=0x7ffe5d180910 "exif:*",
    exception=exception@entry=0x28e7f10) at MagickCore/property.c:1404
#10 0x000000000043e4d8 in GetImageProperty (image=image@entry=0x291aff0,
    property=property@entry=0x7ffe5d180910 "exif:*", exception=exception@entry=0x28e7f10)
    at MagickCore/property.c:2197
#11 0x0000000000441d03 in SetImageProfileInternal (image=image@entry=0x291aff0,
    name=name@entry=0x7ffe5d181990 "exif", profile=profile@entry=0x28ffe30,
    recursive=recursive@entry=MagickFalse, exception=exception@entry=0x28e7f10) at MagickCore/profile.c:1671
#12 0x000000000044297a in SetImageProfile (image=image@entry=0x291aff0, name=name@entry=0x7ffe5d181990 "exif",
    profile=profile@entry=0x28ffe30, exception=exception@entry=0x28e7f10) at MagickCore/profile.c:1678
#13 0x000000000053c922 in ReadProfile (jpeg_info=<optimised out>) at coders/jpeg.c:738
#14 0x00007f1110464975 in ?? () from /usr/lib/x86_64-linux-gnu/libjpeg.so.8
#15 0x00007f11104629ca in ?? () from /usr/lib/x86_64-linux-gnu/libjpeg.so.8
#16 0x00007f111045cf57 in jpeg_consume_input () from /usr/lib/x86_64-linux-gnu/libjpeg.so.8
#17 0x00007f111045d223 in jpeg_read_header () from /usr/lib/x86_64-linux-gnu/libjpeg.so.8
#18 0x000000000053d669 in ReadJPEGImage (image_info=0x28fa130, exception=0x28e7f10) at coders/jpeg.c:1101
#19 0x00000000005a06ee in ReadImage (image_info=image_info@entry=0x28f4b90,
    exception=exception@entry=0x28e7f10) at MagickCore/constitute.c:554
#20 0x0000000000677326 in ReadStream (image_info=image_info@entry=0x28f1910,
    stream=stream@entry=0x59ffb0 <PingStream>, exception=exception@entry=0x28e7f10) at MagickCore/stream.c:1012
#21 0x00000000005a0261 in PingImage (image_info=image_info@entry=0x28ee4f0,
---Type <return> to continue, or q <return> to quit---
    exception=exception@entry=0x28e7f10) at MagickCore/constitute.c:226
#22 0x00000000005a04ab in PingImages (image_info=image_info@entry=0x28ee4f0,
    filename=filename@entry=0x28e7f50 "PoC.jpg", exception=exception@entry=0x28e7f10)
    at MagickCore/constitute.c:326
#23 0x00000000006f2741 in IdentifyImageCommand (image_info=0x28eb2c0, image_info@entry=0x28e8090,
    argc=argc@entry=2, argv=0x28e6490, argv@entry=0x7ffe5d18e4b0, metadata=metadata@entry=0x7ffe5d18c150,
    exception=exception@entry=0x28e7f10) at MagickWand/identify.c:319
#24 0x000000000071a274 in MagickCommandGenesis (image_info=image_info@entry=0x28e8090,
    command=command@entry=0x6f2180 <IdentifyImageCommand>, argc=2, argv=argv@entry=0x7ffe5d18e4b0,
    metadata=0x7ffe5d18d208, exception=exception@entry=0x28e7f10) at MagickWand/mogrify.c:183
#25 0x0000000000411f11 in MagickMain (argc=2, argv=0x7ffe5d18e4b0) at utilities/magick.c:250
#26 0x00007f110bab1f45 in __libc_start_main (main=0x40ec10 <main>, argc=3, argv=0x7ffe5d18e4a8,
    init=<optimised out>, fini=<optimised out>, rtld_fini=<optimised out>, stack_end=0x7ffe5d18e498)
    at libc-start.c:287
#27 0x0000000000411af5 in _start ()


Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail


Current thread: