Buffer over-read in exif_read_data with TIFF IFD tag byte value of 32 bytes
| Sec Bug #70385 | Buffer over-read in exif_read_data with TIFF IFD tag byte value of 32 bytes | ||||
|---|---|---|---|---|---|
| Submitted: | 2015-08-28 18:43 UTC | Modified: | 2015-09-01 18:44 UTC | ||
| From: | hugh at allthethings dot co dot nz | Assigned: | |||
| Status: | Closed | Package: | EXIF related | ||
| PHP Version: | 5.6.13RC1 | OS: | Linux | ||
| Private report: | No | CVE-ID: | None | ||
[2015-08-28 18:43 UTC] hugh at allthethings dot co dot nz
Description: ------------ When supplying a TIFF file that has a tag for one of Make, Model, or Copyright, where the value is exactly 32 bytes (with no null bytes), a buffer over-read occurs. This will cause a crash to happen when compiled with ASAN, or potential data leak when not. The TIFF file that resulted in this bug was found using the american fuzzy-lop (afl) fuzzer. Compiled with ./configure --enable-exif --enable-static --enable-cli --disable-shared --disable-all, with CC of afl-gcc, or if wanting to reproduce without, with CC of gcc, and CFLAGS of -fsanitize=address. Running the test script with the tiff file available at https://transfer.sh/VOhn6/fuzz.tiff The hexdump of file in question is shown below: 00000000 49 49 2a 00 62 00 00 00 30 30 30 30 30 30 30 30 |II*.b...00000000| 00000010 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 |0000000000000000| * 00000060 30 30 03 00 0f 01 30 30 20 00 00 00 30 00 00 00 |00....00 ...0...| 00000070 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 |0000000000000000| * 0000008c The overread happens in the function _estrdup in Zend/zend_alloc.c line 2630 when the call to strlen happens then again on line 2636 when the call to memcpy happens. The cause of this is in the function exif_process_IFD_TAG in ext/exif/exif.c line 2866 (if (byte_count>sizeof(cbuf)) {), where the > should be a >=. This allows a 32 byte string from the TIFF file to be read into the static array cbuf with no trailing null byte, so any string operations read past the buffer. I've attached a patch, and I'm working on a POC exploit for this, but just getting the initial bug report done! Test script: --------------- <?php exif_read_data($argv[1]); ?> Expected result: ---------------- No crash when compiled with ASAN, and no buffer overread when not. A new buffer should be created when value is 32 bytes long, so a 33rd character has a null byte on the end. Actual result: -------------- Warning: exif_read_data(fuzz.tiff): Process tag(x010F=Make ): Illegal format code 0x3030, suppose BYTE in /root/fuzzing/php/exif.php on line 2 ================================================================= ==24169== ERROR: AddressSanitizer: unknown-crash on address 0x7fffffff99e0 at pc 0x7ffff4e5a321 bp 0x7fffffff9830 sp 0x7fffffff9808 READ of size 37 at 0x7fffffff99e0 thread T0 #0 0x7ffff4e5a320 (/usr/lib/x86_64-linux-gnu/libasan.so.0.0.0+0xf320) #1 0xf5b5c4 (/root/php-src/sapi/cli/php+0xf5b5c4) #2 0x805ee2 (/root/php-src/sapi/cli/php+0x805ee2) #3 0x80c2c5 (/root/php-src/sapi/cli/php+0x80c2c5) #4 0x81c9a8 (/root/php-src/sapi/cli/php+0x81c9a8) #5 0x8252f8 (/root/php-src/sapi/cli/php+0x8252f8) #6 0x1775bc5 (/root/php-src/sapi/cli/php+0x1775bc5) #7 0x132fcf0 (/root/php-src/sapi/cli/php+0x132fcf0) #8 0x1117670 (/root/php-src/sapi/cli/php+0x1117670) #9 0xd66dc1 (/root/php-src/sapi/cli/php+0xd66dc1) #10 0x1785466 (/root/php-src/sapi/cli/php+0x1785466) #11 0x434ce8 (/root/php-src/sapi/cli/php+0x434ce8) #12 0x7ffff4382ec4 (/lib/x86_64-linux-gnu/libc-2.19.so+0x21ec4) #13 0x435ec5 (/root/php-src/sapi/cli/php+0x435ec5) Address 0x7fffffff99e0 is located at offset 32 in frame <exif_process_IFD_TAG> of T0's stack: This frame has 3 object(s): [32, 64) 'cbuf' [96, 128) 'tmp' [160, 224) 'tagname' HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext (longjmp and C++ exceptions *are* supported) Shadow bytes around the buggy address: 0x10007fff72e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10007fff72f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10007fff7300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10007fff7310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10007fff7320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x10007fff7330: 00 00 00 00 00 00 00 00 f1 f1 f1 f1[00]00 00 00 0x10007fff7340: f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2 00 00 00 00 0x10007fff7350: 00 00 00 00 f3 f3 f3 f3 00 00 00 00 00 00 00 00 0x10007fff7360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10007fff7370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x10007fff7380: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap righ redzone: fb Freed Heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 ASan internal: fe ==24169== ABORTING (gdb) bt #0 0x00007ffff4397cc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x00007ffff439b0d8 in __GI_abort () at abort.c:89 #2 0x00007ffff4e66829 in ?? () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #3 0x00007ffff4e5d3ec in ?? () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #4 0x00007ffff4e64012 in ?? () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #5 0x00007ffff4e63121 in __asan_report_error () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #6 0x00007ffff4e5a339 in strlen () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #7 0x0000000000f5b5c5 in _estrdup ( s=s@entry=0x7fffffff99e0 '0' <repeats 32 times>, "\263\212\265A") at /root/php-src/Zend/zend_alloc.c:2630 #8 0x0000000000805ee3 in exif_process_IFD_TAG (ImageInfo=0x7fffffffa2e0, dir_entry=<optimized out>, offset_base=<optimized out>, IFDlength=<optimized out>, displacement=0, section_index=3, ReadNextIFD=0, tag_table=0x18efe80 <tag_table_IFD>) at /root/php-src/ext/exif/exif.c:3054 #9 0x000000000080c2c6 in exif_process_IFD_in_TIFF ( ImageInfo=ImageInfo@entry=0x7fffffffa2e0, dir_offset=98, section_index=section_index@entry=3) at /root/php-src/ext/exif/exif.c:3700 #10 0x000000000081c9a9 in exif_scan_FILE_header (ImageInfo=0x7fffffffa2e0) at /root/php-src/ext/exif/exif.c:3794 #11 exif_read_file (ImageInfo=ImageInfo@entry=0x7fffffffa2e0, FileName=<optimized out>, read_thumbnail=<optimized out>, read_all=0) at /root/php-src/ext/exif/exif.c:3903 #12 0x00000000008252f9 in zif_exif_read_data (ht=<optimized out>, return_value=0x7ffff7f963c8, return_value_ptr=<optimized out>, this_ptr=<optimized out>, return_value_used=<optimized out>) at /root/php-src/ext/exif/exif.c:3956 #13 0x0000000001775bc6 in zend_do_fcall_common_helper_SPEC ( execute_data=0x7ffff7f63940) at /root/php-src/Zend/zend_vm_execute.h:558 #14 0x000000000132fcf1 in execute_ex (execute_data=0x7ffff7f63940) at /root/php-src/Zend/zend_vm_execute.h:363 #15 0x0000000001117671 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /root/php-src/Zend/zend.c:1341 #16 0x0000000000d66dc2 in php_execute_script ( primary_file=primary_file@entry=0x7fffffffd2d0) at /root/php-src/main/main.c:2597 #17 0x0000000001785467 in do_cli (argc=3, argv=0x60060000ecb0) at /root/php-src/sapi/cli/php_cli.c:994 #18 0x0000000000434ce9 in main (argc=3, argv=0x60060000ecb0) at /root/php-src/sapi/cli/php_cli.c:1378
Patches
Pull Requests
History
AllCommentsChangesGit/SVN commits
[2015-08-29 05:21 UTC] stas@php.net
[2015-08-29 06:13 UTC] hugh at allthethings dot co dot nz
[2015-08-31 06:19 UTC] stas@php.net
[2015-09-01 08:16 UTC] hugh at allthethings dot co dot nz
[2015-09-01 18:55 UTC] stas@php.net
-Status: Open +Status: Closed