|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-10-21 00:52 UTC] 271193918 at qq dot com
Description:
------------
A malformed input to the function exif_read_data() can cause an out of bounds heap memory read access.
This was found with American Fuzzy Lop.
To test run the cli script on the poc:
USE_ZEND_ALLOC=0 valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --track-origins=yes -v ./php -c exif_read_data.php ./crashes/fuzzer01/id_000194,sig_11,src_024221+025505,op_splice,rep_2
Test script:
---------------
exif_read_data.php
<?php
exif_read_data($argv[1]);
?>
Expected result:
----------------
Part of test logs by Valgrind as follows and All test files are attached.
test@test:~/Desktop/php_test/php-5.6.27/sapi/cli$ uname -a
Linux test 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:34:49 UTC 2016 i686 i686 i686 GNU/Linux
......
==1160== HEAP SUMMARY:
==1160== in use at exit: 19,220 bytes in 10 blocks
==1160== total heap usage: 27,187 allocs, 27,177 frees, 233,036,264 bytes allocated
==1160==
==1160== Searching for pointers to 10 not-freed blocks
==1160== Checked 344,576 bytes
==1160==
==1160== 12 bytes in 1 blocks are still reachable in loss record 1 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43460BF: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x434620A: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4346486: CRYPTO_get_ex_new_index (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42D6BE9: SSL_get_ex_new_index (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6D14: zm_startup_openssl (openssl.c:1153)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160== by 0x8426FA3: zend_hash_apply (zend_hash.c:641)
==1160== by 0x841E3FC: zend_startup_modules (zend_API.c:1930)
==1160==
==1160== 12 bytes in 1 blocks are still reachable in loss record 2 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C2DE9: lh_insert (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43460EC: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x434620A: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4346486: CRYPTO_get_ex_new_index (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42D6BE9: SSL_get_ex_new_index (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6D14: zm_startup_openssl (openssl.c:1153)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160== by 0x8426FA3: zend_hash_apply (zend_hash.c:641)
==1160==
==1160== 16 bytes in 1 blocks are still reachable in loss record 3 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C21BF: sk_new (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42DBE38: ??? (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x42DE083: SSL_COMP_get_compression_methods (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x42E3745: SSL_library_init (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6CEB: zm_startup_openssl (openssl.c:1144)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160== by 0x8426FA3: zend_hash_apply (zend_hash.c:641)
==1160== by 0x841E3FC: zend_startup_modules (zend_API.c:1930)
==1160==
==1160== 16 bytes in 1 blocks are still reachable in loss record 4 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C21BF: sk_new (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C2245: sk_new_null (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43460D6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x434620A: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4346486: CRYPTO_get_ex_new_index (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42D6BE9: SSL_get_ex_new_index (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6D14: zm_startup_openssl (openssl.c:1153)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160==
==1160== 20 bytes in 1 blocks are still reachable in loss record 5 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C21A6: sk_new (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42DBE38: ??? (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x42DE083: SSL_COMP_get_compression_methods (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x42E3745: SSL_library_init (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6CEB: zm_startup_openssl (openssl.c:1144)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160== by 0x8426FA3: zend_hash_apply (zend_hash.c:641)
==1160== by 0x841E3FC: zend_startup_modules (zend_API.c:1930)
==1160==
==1160== 20 bytes in 1 blocks are still reachable in loss record 6 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C21A6: sk_new (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C2245: sk_new_null (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43460D6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x434620A: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4346486: CRYPTO_get_ex_new_index (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42D6BE9: SSL_get_ex_new_index (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6D14: zm_startup_openssl (openssl.c:1153)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160==
==1160== 20 bytes in 1 blocks are still reachable in loss record 7 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x434622A: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4346486: CRYPTO_get_ex_new_index (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42D6BE9: SSL_get_ex_new_index (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6D14: zm_startup_openssl (openssl.c:1153)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160== by 0x8426FA3: zend_hash_apply (zend_hash.c:641)
==1160== by 0x841E3FC: zend_startup_modules (zend_API.c:1930)
==1160== by 0x839C3ED: php_module_startup (main.c:2323)
==1160==
==1160== 64 bytes in 1 blocks are still reachable in loss record 8 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C2ACF: lh_new (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4345FF5: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43460A4: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x434620A: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4346486: CRYPTO_get_ex_new_index (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42D6BE9: SSL_get_ex_new_index (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6D14: zm_startup_openssl (openssl.c:1153)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160==
==1160== 96 bytes in 1 blocks are still reachable in loss record 9 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x43444B6: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4344A8E: CRYPTO_malloc (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43C2AB5: lh_new (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4345FF5: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x43460A4: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x434620A: ??? (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x4346486: CRYPTO_get_ex_new_index (in /lib/i386-linux-gnu/libcrypto.so.1.0.0)
==1160== by 0x42D6BE9: SSL_get_ex_new_index (in /lib/i386-linux-gnu/libssl.so.1.0.0)
==1160== by 0x80B6D14: zm_startup_openssl (openssl.c:1153)
==1160== by 0x841DF6A: zend_startup_module_ex (zend_API.c:1797)
==1160== by 0x841DFCF: zend_startup_module_int (zend_API.c:1810)
==1160==
==1160== 18,944 bytes in 1 blocks are still reachable in loss record 10 of 10
==1160== at 0x402D1AE: malloc (vg_replace_malloc.c:299)
==1160== by 0x61A95BA: ??? (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21)
==1160== by 0x400F364: call_init.part.0 (dl-init.c:72)
==1160== by 0x400F48D: call_init (dl-init.c:30)
==1160== by 0x400F48D: _dl_init (dl-init.c:120)
==1160== by 0x4000AFE: ??? (in /lib/i386-linux-gnu/ld-2.23.so)
==1160==
==1160== LEAK SUMMARY:
==1160== definitely lost: 0 bytes in 0 blocks
==1160== indirectly lost: 0 bytes in 0 blocks
==1160== possibly lost: 0 bytes in 0 blocks
==1160== still reachable: 19,220 bytes in 10 blocks
==1160== suppressed: 0 bytes in 0 blocks
==1160==
==1160== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==1160== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Actual result:
--------------
test@test:~/Desktop/php_test/php-5.6.27/sapi/cli$ gdb -q --args ./php -c exif_read_data.php ./crashes/fuzzer01/id_000194,sig_11,src_024221+025505,op_splice,rep_2
Reading symbols from ./php...done.
(gdb) r
......
Fatal error: Allowed memory size of 134217728 bytes exhausted at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_vm_execute.h:12902 (tried to allocate 27751964 bytes) in /home/test/Desktop/php_test/php-5.6.27/sapi/cli/crashes/fuzzer01/id_000194,sig_11,src_024221+025505,op_splice,rep_2 on line 65
Program received signal SIGSEGV, Segmentation fault.
0x084153a1 in _zval_dtor_func (zvalue=0xb59cfd3c, __zend_filename=0x891c7cc "/home/test/Desktop/php_test/php-5.6.27/Zend/zend_execute.h",
__zend_lineno=79) at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_variables.c:36
36 CHECK_ZVAL_STRING_REL(zvalue);
(gdb) bt
#0 0x084153a1 in _zval_dtor_func (zvalue=0xb59cfd3c, __zend_filename=0x891c7cc "/home/test/Desktop/php_test/php-5.6.27/Zend/zend_execute.h",
__zend_lineno=79) at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_variables.c:36
#1 0x08404c3e in _zval_dtor (zvalue=0xb59cfd3c, __zend_filename=0x891c7cc "/home/test/Desktop/php_test/php-5.6.27/Zend/zend_execute.h",
__zend_lineno=79) at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_variables.h:35
#2 0x08404cd1 in i_zval_ptr_dtor (zval_ptr=0xb59cfd3c, __zend_filename=0x891e99c "/home/test/Desktop/php_test/php-5.6.27/Zend/zend_variables.c",
__zend_lineno=188) at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_execute.h:79
#3 0x08405a3a in _zval_ptr_dtor (zval_ptr=0xb5d1b43c, __zend_filename=0x891e99c "/home/test/Desktop/php_test/php-5.6.27/Zend/zend_variables.c",
__zend_lineno=188) at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_execute_API.c:424
#4 0x084157bf in _zval_ptr_dtor_wrapper (zval_ptr=0xb5d1b43c) at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_variables.c:188
#5 0x08425634 in i_zend_hash_bucket_delete (ht=0x89ba6fc <executor_globals+188>, p=0xb5d1b430)
at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_hash.c:182
#6 0x084256e4 in zend_hash_bucket_delete (ht=0x89ba6fc <executor_globals+188>, p=0xb5d1b430)
at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_hash.c:192
#7 0x08426ed8 in zend_hash_graceful_reverse_destroy (ht=0x89ba6fc <executor_globals+188>)
at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_hash.c:613
#8 0x084054d3 in shutdown_executor () at /home/test/Desktop/php_test/php-5.6.27/Zend/zend_execute_API.c:244
#9 0x08417423 in zend_deactivate () at /home/test/Desktop/php_test/php-5.6.27/Zend/zend.c:960
#10 0x0839ba36 in php_request_shutdown (dummy=0x0) at /home/test/Desktop/php_test/php-5.6.27/main/main.c:1899
#11 0x084b3943 in do_cli (argc=4, argv=0x89c1ac0) at /home/test/Desktop/php_test/php-5.6.27/sapi/cli/php_cli.c:1181
#12 0x084b4064 in main (argc=4, argv=0x89c1ac0) at /home/test/Desktop/php_test/php-5.6.27/sapi/cli/php_cli.c:1382
(gdb)
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Nov 03 05:00:01 2025 UTC |
If compile php 5.6.27 with Asan: run without USE_ZEND_ALLOC=0 , test log as follows: ./php -c ./crashes/exif_read_data.php ./crashes/fuzzer01/id_000194,sig_11,src_024221+025505,op_splice,rep_2 Fatal error: Allowed memory size of 134217728 bytes exhausted at /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_vm_execute.h:12902 (tried to allocate 27751964 bytes) in /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/sapi/cli/crashes/fuzzer01/id_000194,sig_11,src_024221+025505,op_splice,rep_2 on line 65 ASAN:SIGSEGV ================================================================= ==18377==ERROR: AddressSanitizer: SEGV on unknown address 0xa70bce4b (pc 0x08b06f17 bp 0xbfbf2b98 sp 0xbfbf2b70 T0) #0 0x8b06f16 in _zval_dtor_func /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_variables.c:36 #1 0x8aca1af in _zval_dtor /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_variables.h:35 #2 0x8aca2bd in i_zval_ptr_dtor /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_execute.h:79 #3 0x8acd46f in _zval_ptr_dtor /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_execute_API.c:424 #4 0x8b07ce6 in _zval_ptr_dtor_wrapper /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_variables.c:188 #5 0x8b40672 in i_zend_hash_bucket_delete /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_hash.c:182 #6 0x8b4082e in zend_hash_bucket_delete /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_hash.c:192 #7 0x8b4639a in zend_hash_graceful_reverse_destroy /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_hash.c:613 #8 0x8acc193 in shutdown_executor /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_execute_API.c:244 #9 0x8b0dc11 in zend_deactivate /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend.c:960 #10 0x89a6b76 in php_request_shutdown /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/main/main.c:1899 #11 0x8d6e3d9 in do_cli /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/sapi/cli/php_cli.c:1181 #12 0x8d6f0bd in main /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/sapi/cli/php_cli.c:1382 #13 0xb6ba3636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636) #14 0x8067730 (/home/test/Desktop/php_test/php-5.6.27-gcc-Asan/sapi/cli/php+0x8067730) AddressSanitizer can not provide additional info. SUMMARY: AddressSanitizer: SEGV /home/test/Desktop/php_test/php-5.6.27-gcc-Asan/Zend/zend_variables.c:36 _zval_dtor_func ==18377==ABORTINGThis may be not related directly to this issue, but current exif code does not validate Unicode strings properly. 2634 /* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX */ 2635 if (!to || !from || zend_multibyte_encoding_converter( 2636 (unsigned char**)pszInfoPtr, 2637 &len, 2638 (unsigned char*)szValuePtr, 2639 ByteCount, 2640 to, 2641 from) == (size_t)-1) { 2642 len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount); This doesn't seem good. We are better to return nothing when encoding is broken, just like htmlspecialchars()/htmlentities(). @cmd Could you handle this issue. Just returning len=0 seems to work at glance. If user insist to get broken data, we may provide function or ini option.