|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2016-06-19 04:50 UTC] stas@php.net
-Assigned To:
+Assigned To: stas
[2016-06-19 04:50 UTC] stas@php.net
[2016-06-20 18:16 UTC] shm@php.net
[2016-06-21 06:46 UTC] stas@php.net
-PHP Version: 7.0Git-2016-06-14 (Git)
+PHP Version: 5.5.36
[2016-06-21 06:48 UTC] stas@php.net
[2016-06-21 06:48 UTC] stas@php.net
-Status: Assigned
+Status: Closed
[2016-06-21 07:03 UTC] stas@php.net
[2016-06-21 07:26 UTC] stas@php.net
[2016-06-21 07:27 UTC] stas@php.net
[2016-06-22 05:58 UTC] krakjoe@php.net
[2016-06-23 12:50 UTC] kaplan@php.net
-CVE-ID:
+CVE-ID: 2016-5768
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 10:00:01 2025 UTC |
Description: ------------ # short description _php_mb_regex_ereg_replace_exec when called by mb_ereg_replace_callback frees the description twice in case when callback execution failed (i.e. threw am exception). # why I think it's security issue? callbacks used in mb_ereg_replace_callback are usually provided by the script author, but may fail in many cases on particular input. In that case, PHP interpreter will free memory twice, which may be used to allocate memory area for two distinct purposes. So if remote attacker is able to trigger this bug remotely (which depends heavily on callbacks used with this function), then this bug may be exploited to gain code execution. But feel free to evaluate this bug whatever you want. :) # code #10 0x0000000000a9fe3f in _php_mb_regex_ereg_replace_exec (execute_data=0x7ffff23b98e0, return_value=0x7ffff23b98c0, options=0xc, is_callable=0x1) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1012 1012 efree(description); gdb-peda$ list 1007 } 1008 onig_region_free(regs, 0); 1009 } 1010 1011 if (description) { 1012 efree(description); 1013 } 1014 if (regs != NULL) { 1015 onig_region_free(regs, 1); 1016 } gdb-peda$ list -40 972 /* null terminate buffer */ 973 smart_str_0(&eval_buf); 974 975 arg_replace_fci.param_count = 1; 976 arg_replace_fci.params = args; 977 arg_replace_fci.retval = &retval; 978 if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache) == SUCCESS && 979 !Z_ISUNDEF(retval)) { 980 convert_to_string_ex(&retval); 981 smart_str_appendl(&out_buf, Z_STRVAL(retval), Z_STRLEN(retval)); gdb-peda$ 982 smart_str_free(&eval_buf); 983 zval_ptr_dtor(&retval); 984 } else { 985 efree(description); 986 if (!EG(exception)) { 987 php_error_docref(NULL, E_WARNING, "Unable to call custom replacement function"); 988 } 989 } 990 zval_ptr_dtor(&subpats); 991 } gdb-peda$ 992 993 n = regs->end[0]; 994 if ((pos - (OnigUChar *)string) < n) { 995 pos = (OnigUChar *)string + n; 996 } else { 997 if (pos < string_lim) { 998 smart_str_appendl(&out_buf, (char *)pos, 1); 999 } 1000 pos++; 1001 } gdb-peda$ 1002 } else { /* nomatch */ 1003 /* stick that last bit of string on our output */ 1004 if (string_lim - pos > 0) { 1005 smart_str_appendl(&out_buf, (char *)pos, string_lim - pos); 1006 } 1007 } 1008 onig_region_free(regs, 0); 1009 } 1010 1011 if (description) { gdb-peda$ 1012 efree(description); 1013 } decsription is freed twice in 1012 and 984 lines, as shown here: Breakpoint 6, _php_mb_regex_ereg_replace_exec (execute_data=0x7ffff2a150e0, return_value=0x7ffff2a150c0, options=0xc, is_callable=0x1) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:985 985 efree(description); gdb-peda$ print description $5 = 0x7ffff2a80200 "/home/shm/research/svn/notes/0day/php/php7/full Breakpoint 5, _php_mb_regex_ereg_replace_exec (execute_data=0x7ffff2a150e0, return_value=0x7ffff2a150c0, options=0xc, is_callable=0x1) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1012 1012 efree(description); gdb-peda$ print description $6 = 0x7ffff2a80200 "" ASAN report bt: bt #0 0x00007ffff3596cc9 in __GI_raise (sig=sig@entry=0x6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x00007ffff359a0d8 in __GI_abort () at abort.c:89 #2 0x00007ffff4e667f9 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 0x00007ffff4e63fe2 in ?? () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #5 0x00007ffff4e636e1 in ?? () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #6 0x00007ffff4e6265f in ?? () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #7 0x00007ffff4e53a18 in ?? () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #8 0x00007ffff4e60368 in free () from /usr/lib/x86_64-linux-gnu/libasan.so.0 #9 0x0000000000f87b2f in _efree (ptr=0x60220001fa80, __zend_filename=0x18d7dc0 "/home/shm/src/php-src/ext/mbstring/php_mbregex.c", __zend_lineno=0x3f4, __zend_orig_filename=0x0, __zend_orig_lineno=0x0) at /home/shm/src/php-src/Zend/zend_alloc.c:2461 #10 0x0000000000a9fe3f in _php_mb_regex_ereg_replace_exec (execute_data=0x7ffff23b98e0, return_value=0x7ffff23b98c0, options=0xc, is_callable=0x1) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1012 #11 0x0000000000aa0257 in zif_mb_ereg_replace_callback (execute_data=0x7ffff23b98e0, return_value=0x7ffff23b98c0) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1051 #12 0x00000000010fe846 in ZEND_DO_ICALL_SPEC_HANDLER () at /home/shm/src/php-src/Zend/zend_vm_execute.h:586 #13 0x00000000010fd8bf in execute_ex (ex=0x7ffff23b9830) at /home/shm/src/php-src/Zend/zend_vm_execute.h:414 #14 0x00000000010fdb1a in zend_execute (op_array=0x60220001fba0, return_value=0x0) at /home/shm/src/php-src/Zend/zend_vm_execute.h:458 #15 0x0000000001012aef in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/shm/src/php-src/Zend/zend.c:1427 #16 0x0000000000ea2159 in php_execute_script (primary_file=0x7fffffffcb30) at /home/shm/src/php-src/main/main.c:2494 #17 0x000000000122931c in do_cli (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:974 #18 0x000000000122b8f8 in main (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:1344 #19 0x00007ffff3581ec5 in __libc_start_main (main=0x122a3d0 <main>, argc=0x2, argv=0x7fffffffe038, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe028) at libc-start.c:287 #20 0x000000000042dc49 in _start () Test script: --------------- <?php function exception_handler($exception) { echo "Uncaught exception: " , $exception->getMessage(), "\n"; } $var10 = "exception_handler"; $var14 = mb_ereg_replace_callback("", $var10, ""); Expected result: ---------------- description is freed once Actual result: -------------- description is freed twice