php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72399 Use-After-Free in MBString (search_re)
Submitted: 2016-06-13 20:33 UTC Modified: 2016-06-14 08:28 UTC
From: shm@php.net Assigned: laruence
Status: Closed Package: mbstring related
PHP Version: 7.0Git-2016-06-13 (Git) OS:
Private report: No CVE-ID:
 [2016-06-13 20:33 UTC] shm@php.net
Description:
------------
mbsearch is prone to use-after-free of global search_re memory, which in worst case can be used to gain code execution (when attacker is able to allocate memory that will be used in mbereg_search_pos).

### 1. search_re global is setup by mb_search_init

Breakpoint 2, php_mbregex_compile_pattern (pattern=0x60060004ff78 "2", patlen=0x1, options=0xc, enc=0x1f3e120 <OnigEncodingUTF8>, 
    syntax=0x1f39aa0 <OnigSyntaxRuby>) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:456
456                     if ((err_code = onig_new(&retval, (OnigUChar *)pattern, (OnigUChar *)(pattern + patlen), options, enc, syntax, &err_info)) != ONIG_NO{
gdb-peda$ bt
#0  php_mbregex_compile_pattern (pattern=0x60060004ff78 "2", patlen=0x1, options=0xc, enc=0x1f3e120 <OnigEncodingUTF8>, syntax=0x1f39aa0 <OnigSyntaxRuby>)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:456
#1  0x0000000000aa26f6 in zif_mb_ereg_search_init (execute_data=0x7ffff23b9920, return_value=0x7ffff23b98c0)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1341
#2  0x00000000010fe846 in ZEND_DO_ICALL_SPEC_HANDLER () at /home/shm/src/php-src/Zend/zend_vm_execute.h:586
#3  0x00000000010fd8bf in execute_ex (ex=0x7ffff23b9830) at /home/shm/src/php-src/Zend/zend_vm_execute.h:414
#4  0x00000000010fdb1a in zend_execute (op_array=0x60220001fba0, return_value=0x0) at /home/shm/src/php-src/Zend/zend_vm_execute.h:458
#5  0x0000000001012aef in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/shm/src/php-src/Zend/zend.c:1427
#6  0x0000000000ea2159 in php_execute_script (primary_file=0x7fffffffcb30) at /home/shm/src/php-src/main/main.c:2494
#7  0x000000000122931c in do_cli (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:974
#8  0x000000000122b8f8 in main (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:1344
#9  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
#10 0x000000000042dc49 in _start ()

### 2. mb_eregi_replace compiles same pattern (but result won't be stored under search_re global

Breakpoint 2, php_mbregex_compile_pattern (pattern=0x60060004ff78 "2", patlen=0x1, options=0xd, enc=0x1f3e120 <OnigEncodingUTF8>, 
    syntax=0x1f39aa0 <OnigSyntaxRuby>) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:456
456                     if ((err_code = onig_new(&retval, (OnigUChar *)pattern, (OnigUChar *)(pattern + patlen), options, enc, syntax, &err_info)) != ONIG_NO{
gdb-peda$ bt
#0  php_mbregex_compile_pattern (pattern=0x60060004ff78 "2", patlen=0x1, options=0xd, enc=0x1f3e120 <OnigEncodingUTF8>, syntax=0x1f39aa0 <OnigSyntaxRuby>)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:456
#1  0x0000000000a9ecdb in _php_mb_regex_ereg_replace_exec (execute_data=0x7ffff23b9920, return_value=0x7ffff23b98e0, options=0xd, is_callable=0x0)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:868
#2  0x0000000000aa022b in zif_mb_eregi_replace (execute_data=0x7ffff23b9920, return_value=0x7ffff23b98e0)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1043
#3  0x00000000010fe846 in ZEND_DO_ICALL_SPEC_HANDLER () at /home/shm/src/php-src/Zend/zend_vm_execute.h:586
#4  0x00000000010fd8bf in execute_ex (ex=0x7ffff23b9830) at /home/shm/src/php-src/Zend/zend_vm_execute.h:414
#5  0x00000000010fdb1a in zend_execute (op_array=0x60220001fba0, return_value=0x0) at /home/shm/src/php-src/Zend/zend_vm_execute.h:458
#6  0x0000000001012aef in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/shm/src/php-src/Zend/zend.c:1427
#7  0x0000000000ea2159 in php_execute_script (primary_file=0x7fffffffcb30) at /home/shm/src/php-src/main/main.c:2494
#8  0x000000000122931c in do_cli (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:974
#9  0x000000000122b8f8 in main (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:1344
#10 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
#11 0x000000000042dc49 in _start ()

gdb-peda$ up
#1  0x0000000000a9ecdb in _php_mb_regex_ereg_replace_exec (execute_data=0x7ffff23b9920, return_value=0x7ffff23b98e0, options=0xd, is_callable=0x0)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:868
868             re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax);

### 3. in same the same call, reg for previous "2" pattern will be freed, but it's still referenced by global search_re 

Breakpoint 1, onig_free (reg=0x60300000fa40) at /home/shm/src/php-src/ext/mbstring/oniguruma/regcomp.c:5202
5202        xfree(reg);
gdb-peda$ bt
#0  onig_free (reg=0x60300000fa40) at /home/shm/src/php-src/ext/mbstring/oniguruma/regcomp.c:5202
#1  0x0000000000a9bed4 in php_mb_regex_free_cache (el=0x60260001ca40) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:59
#2  0x000000000104335e in _zend_hash_add_or_update_i (ht=0x601a0000cf80, key=0x60060007b6a0, pData=0x7fffffff98d0, flag=0x1, 
    __zend_filename=0x18d7d60 "/home/shm/src/php-src/Zend/zend_hash.h", __zend_lineno=0x222) at /home/shm/src/php-src/Zend/zend_hash.c:596
#3  0x0000000001043c68 in _zend_hash_str_update (ht=0x601a0000cf80, str=0x60060004ff78 "2", len=0x1, pData=0x7fffffff98d0, 
    __zend_filename=0x18d7d60 "/home/shm/src/php-src/Zend/zend_hash.h", __zend_lineno=0x222) at /home/shm/src/php-src/Zend/zend_hash.c:667
#4  0x0000000000a9b899 in zend_hash_str_update_ptr (ht=0x601a0000cf80, str=0x60060004ff78 "2", len=0x1, pData=0x60300000f840)
    at /home/shm/src/php-src/Zend/zend_hash.h:546
#5  0x0000000000a9cdf6 in php_mbregex_compile_pattern (pattern=0x60060004ff78 "2", patlen=0x1, options=0xd, enc=0x1f3e120 <OnigEncodingUTF8>, 
    syntax=0x1f39aa0 <OnigSyntaxRuby>) at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:462
#6  0x0000000000a9ecdb in _php_mb_regex_ereg_replace_exec (execute_data=0x7ffff23b9920, return_value=0x7ffff23b98e0, options=0xd, is_callable=0x0)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:868
#7  0x0000000000aa022b in zif_mb_eregi_replace (execute_data=0x7ffff23b9920, return_value=0x7ffff23b98e0)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1043
#8  0x00000000010fe846 in ZEND_DO_ICALL_SPEC_HANDLER () at /home/shm/src/php-src/Zend/zend_vm_execute.h:586
#9  0x00000000010fd8bf in execute_ex (ex=0x7ffff23b9830) at /home/shm/src/php-src/Zend/zend_vm_execute.h:414
#10 0x00000000010fdb1a in zend_execute (op_array=0x60220001fba0, return_value=0x0) at /home/shm/src/php-src/Zend/zend_vm_execute.h:458
#11 0x0000000001012aef in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/shm/src/php-src/Zend/zend.c:1427
#12 0x0000000000ea2159 in php_execute_script (primary_file=0x7fffffffcb30) at /home/shm/src/php-src/main/main.c:2494
#13 0x000000000122931c in do_cli (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:974
#14 0x000000000122b8f8 in main (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:1344
#15 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
#16 0x000000000042dc49 in _start ()


### 4. search_re is referenced in mb_ereg_search_pos

Stopped reason: SIGABRT
0x00007ffff3596cc9 in __GI_raise (sig=sig@entry=0x6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56      ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
gdb-peda$ 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  0x00007ffff4e630f1 in __asan_report_error () from /usr/lib/x86_64-linux-gnu/libasan.so.0
#6  0x00007ffff4e5d704 in __asan_report_load4 () from /usr/lib/x86_64-linux-gnu/libasan.so.0
#7  0x00000000009db00d in onig_search (reg=0x60300000fa40, str=0x60060000ec68 "", end=0x60060000ec68 "", start=0x60060000ec68 "", range=0x60060000ec68 "", 
    region=0x60060007b640, option=0x0) at /home/shm/src/php-src/ext/mbstring/oniguruma/regexec.c:3397
#8  0x0000000000aa17b7 in _php_mb_regex_ereg_search_exec (execute_data=0x7ffff23b9920, return_value=0x7ffff23b9900, mode=0x1)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1234
#9  0x0000000000aa2337 in zif_mb_ereg_search_pos (execute_data=0x7ffff23b9920, return_value=0x7ffff23b9900)
    at /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1299
#10 0x00000000010fe846 in ZEND_DO_ICALL_SPEC_HANDLER () at /home/shm/src/php-src/Zend/zend_vm_execute.h:586
#11 0x00000000010fd8bf in execute_ex (ex=0x7ffff23b9830) at /home/shm/src/php-src/Zend/zend_vm_execute.h:414
#12 0x00000000010fdb1a in zend_execute (op_array=0x60220001fba0, return_value=0x0) at /home/shm/src/php-src/Zend/zend_vm_execute.h:458
#13 0x0000000001012aef in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/shm/src/php-src/Zend/zend.c:1427
#14 0x0000000000ea2159 in php_execute_script (primary_file=0x7fffffffcb30) at /home/shm/src/php-src/main/main.c:2494
#15 0x000000000122931c in do_cli (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:974
#16 0x000000000122b8f8 in main (argc=0x2, argv=0x60060000ed40) at /home/shm/src/php-src/sapi/cli/php_cli.c:1344
#17 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
#18 0x000000000042dc49 in _start ()

ASAN report:

$ ASAN_OPTIONS=symbolize=1 ./php minerva.147.1555293821
=================================================================
==24278== ERROR: AddressSanitizer: heap-use-after-free on address 0x60300000fa54 at pc 0x9db00d bp 0x7fff52215ad0 sp 0x7fff52215ac8
READ of size 4 at 0x60300000fa54 thread T0
    #0 0x9db00c in onig_search /home/shm/src/php-src/ext/mbstring/oniguruma/regexec.c:3397
    #1 0xaa17b6 in _php_mb_regex_ereg_search_exec /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1234
    #2 0xaa2336 in zif_mb_ereg_search_pos /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1299
    #3 0x10fe845 in ZEND_DO_ICALL_SPEC_HANDLER /home/shm/src/php-src/Zend/zend_vm_execute.h:586
    #4 0x10fd8be in execute_ex /home/shm/src/php-src/Zend/zend_vm_execute.h:414
    #5 0x10fdb19 in zend_execute /home/shm/src/php-src/Zend/zend_vm_execute.h:458
    #6 0x1012aee in zend_execute_scripts /home/shm/src/php-src/Zend/zend.c:1427
    #7 0xea2158 in php_execute_script /home/shm/src/php-src/main/main.c:2494
    #8 0x122931b in do_cli /home/shm/src/php-src/sapi/cli/php_cli.c:974
    #9 0x122b8f7 in main /home/shm/src/php-src/sapi/cli/php_cli.c:1344
    #10 0x7f16a28a9ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
    #11 0x42dc48 in _start (/home/shm/src/php-src/sapi/cli/php+0x42dc48)
0x60300000fa54 is located 20 bytes inside of 440-byte region [0x60300000fa40,0x60300000fbf8)
freed by thread T0 here:
    #0 0x7f16a41a533a (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x1533a)
    #1 0x9bfba9 in onig_free /home/shm/src/php-src/ext/mbstring/oniguruma/regcomp.c:5202
    #2 0xa9bed3 in php_mb_regex_free_cache /home/shm/src/php-src/ext/mbstring/php_mbregex.c:59
    #3 0x104335d in _zend_hash_add_or_update_i /home/shm/src/php-src/Zend/zend_hash.c:596
    #4 0x1043c67 in _zend_hash_str_update /home/shm/src/php-src/Zend/zend_hash.c:667
    #5 0xa9b898 in zend_hash_str_update_ptr /home/shm/src/php-src/Zend/zend_hash.h:546
    #6 0xa9cdf5 in php_mbregex_compile_pattern /home/shm/src/php-src/ext/mbstring/php_mbregex.c:462
    #7 0xa9ecda in _php_mb_regex_ereg_replace_exec /home/shm/src/php-src/ext/mbstring/php_mbregex.c:868
    #8 0xaa022a in zif_mb_eregi_replace /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1043
    #9 0x10fe845 in ZEND_DO_ICALL_SPEC_HANDLER /home/shm/src/php-src/Zend/zend_vm_execute.h:586
    #10 0x10fd8be in execute_ex /home/shm/src/php-src/Zend/zend_vm_execute.h:414
    #11 0x10fdb19 in zend_execute /home/shm/src/php-src/Zend/zend_vm_execute.h:458
    #12 0x1012aee in zend_execute_scripts /home/shm/src/php-src/Zend/zend.c:1427
    #13 0xea2158 in php_execute_script /home/shm/src/php-src/main/main.c:2494
    #14 0x122931b in do_cli /home/shm/src/php-src/sapi/cli/php_cli.c:974
    #15 0x122b8f7 in main /home/shm/src/php-src/sapi/cli/php_cli.c:1344
    #16 0x7f16a28a9ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
previously allocated by thread T0 here:
    #0 0x7f16a41a541a (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x1541a)
    #1 0x9c1960 in onig_new /home/shm/src/php-src/ext/mbstring/oniguruma/regcomp.c:5539
    #2 0xa9cd18 in php_mbregex_compile_pattern /home/shm/src/php-src/ext/mbstring/php_mbregex.c:456
    #3 0xaa26f5 in zif_mb_ereg_search_init /home/shm/src/php-src/ext/mbstring/php_mbregex.c:1341
    #4 0x10fe845 in ZEND_DO_ICALL_SPEC_HANDLER /home/shm/src/php-src/Zend/zend_vm_execute.h:586
    #5 0x10fd8be in execute_ex /home/shm/src/php-src/Zend/zend_vm_execute.h:414
    #6 0x10fdb19 in zend_execute /home/shm/src/php-src/Zend/zend_vm_execute.h:458
    #7 0x1012aee in zend_execute_scripts /home/shm/src/php-src/Zend/zend.c:1427
    #8 0xea2158 in php_execute_script /home/shm/src/php-src/main/main.c:2494
    #9 0x122931b in do_cli /home/shm/src/php-src/sapi/cli/php_cli.c:974
    #10 0x122b8f7 in main /home/shm/src/php-src/sapi/cli/php_cli.c:1344
    #11 0x7f16a28a9ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
SUMMARY: AddressSanitizer: heap-use-after-free /home/shm/src/php-src/ext/mbstring/oniguruma/regexec.c:3397 onig_search
Shadow bytes around the buggy address:
  0x0c067fff9ef0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff9f00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c067fff9f10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff9f20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff9f30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
=>0x0c067fff9f40: fa fa fa fa fa fa fa fa fd fd[fd]fd fd fd fd fd
  0x0c067fff9f50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c067fff9f60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c067fff9f70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x0c067fff9f80: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c067fff9f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 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
==24278== ABORTING

Test script:
---------------
<?php
$var5 = mbereg_search_init("","2");
$var6 = mb_eregi_replace("2","","");
$var13 = mbereg_search_pos();

Expected result:
----------------
No use-after-free present in the code

Actual result:
--------------
use-after-free present in the code

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-13 20:34 UTC] shm@php.net
-PHP Version: 7.1Git-2016-06-13 (Git) +PHP Version: 7.0Git-2016-06-13 (Git)
 [2016-06-13 20:34 UTC] shm@php.net
7.1 -> 7.0
 [2016-06-14 01:17 UTC] laruence@php.net
-Type: Security +Type: Bug
 [2016-06-14 01:17 UTC] laruence@php.net
this is not a security issue, as you need specially codes to trigger it
 [2016-06-14 01:20 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3d5641872239cbd4ec8855b05c90f94fb0d11d7e
Log: Fixed bug #72399 (Use-After-Free in MBString (search_re))
 [2016-06-14 01:20 UTC] laruence@php.net
-Status: Open +Status: Closed
 [2016-06-14 06:32 UTC] shm@php.net
I'm not sure what we consider as a security issue. Previously bugs like this one were marked as security bugs (it can be used to bypass disable_functions upon code execution is done, potentially code to trigger that issue could be also present in popular script). Do we have any policy on this subject?
 [2016-06-14 07:57 UTC] stas@php.net
-Assigned To: +Assigned To: stas
 [2016-06-14 07:57 UTC] stas@php.net
Yes, we do. Issues that require local access to trigger do not considered as a rule security issues, since once you can run code on a local host, you can do anything anyway.
 [2016-06-14 07:57 UTC] stas@php.net
-Assigned To: stas +Assigned To: laruence
 [2016-06-14 08:28 UTC] shm@php.net
Thanks for the clarification. Still, shown code pattern could be used in popular script, thus it would let to perform attack from the remote.

I don't want to force this bug (or any other as a security issue), but I'm just a little bit confused - what's the difference between this one and https://bugs.php.net/bug.php?id=72093 this one for example.
 [2016-06-22 05:58 UTC] krakjoe@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3d5641872239cbd4ec8855b05c90f94fb0d11d7e
Log: Fixed bug #72399 (Use-After-Free in MBString (search_re))
 [2016-07-20 11:30 UTC] davey@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3d5641872239cbd4ec8855b05c90f94fb0d11d7e
Log: Fixed bug #72399 (Use-After-Free in MBString (search_re))
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC