PHP :: Sec Bug #77371 :: heap buffer overflow in mb regex functions

Sec Bug #77371 heap buffer overflow in mb regex functions - compile_string_node
Submitted: 2018-12-29 22:29 UTC Modified: 2019-02-22 22:08 UTC
From: hugh at allthethings dot co dot nz Assigned: stas (profile)
Status: Closed Package: mbstring related
PHP Version: 5.6.39 OS: Linux
Private report: No CVE-ID: 2019-9023

 [2018-12-29 22:29 UTC] hugh at allthethings dot co dot nz

Description:
------------
After patching for #77370, I found another heap buffer overflow, based on incomplete multibyte strings in $pattern in mb regex functions such as mb_ereg, mb_split.

Narrowed the bug down to the compile_string_node function in ext/mbstring/oniguruma/regcomp.c. In the function, the length of a string is calculated, and is used in add_compile_string. If the string has an unfinished multibyte character at the end of the string, then the length will overflow the end of the buffer.

This could cause memory corruption and/or leakage.

Reproduced on 5.6, 7.0 and 7.1 (after patch for #77370 is applied, otherwise that case gets hit first). 7.2, 7.3 and master don't have this bug due to not having the file.

Patch is available at https://gist.github.com/hughdavenport/89849d35cc27c2242edcce4eb7c93520



Test script:
---------------
php -r 'var_dump(mb_ereg("()0\xfc00000\xfc00000\xfc00000\xfc",""));'

the patch from #77370 needs to be applied first to get to this point.

Expected result:
----------------
no crash

Actual result:
--------------
$ ~/php-5.6.39/sapi/cli/php -r 'var_dump(mb_ereg("()0\xfc00000\xfc00000\xfc00000\xfc",""));'
=================================================================
==4295==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000002c38 at pc 0x0000004d67d1 bp 0x7fff747ef860 sp 0x7fff747ef010
READ of size 24 at 0x606000002c38 thread T0
    #0 0x4d67d0 in __asan_memcpy (/home/hugh/php-5.6.39/sapi/cli/php+0x4d67d0)
    #1 0x847418 in add_bytes /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:284:3
    #2 0x847418 in add_compile_string /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:452
    #3 0x81a59a in compile_string_node /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:541:10
    #4 0x81a59a in compile_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:1627
    #5 0x8164f8 in compile_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:1590:11
    #6 0x8092a5 in onig_compile /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5390:7
    #7 0x82df69 in onig_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5545:7
    #8 0x9a7775 in php_mbregex_compile_pattern /home/hugh/php-5.6.39/ext/mbstring/php_mbregex.c:458:19
    #9 0x9a06e9 in _php_mb_regex_ereg_exec /home/hugh/php-5.6.39/ext/mbstring/php_mbregex.c:728:7
    #10 0x11a26b8 in zend_do_fcall_common_helper_SPEC /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:558:5
    #11 0xffc61d in execute_ex /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:363:14
    #12 0xffe602 in zend_execute /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:388:2
    #13 0xebe437 in zend_eval_stringl /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1080:4
    #14 0xebfbb9 in zend_eval_stringl_ex /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1127:11
    #15 0xebfbb9 in zend_eval_string_ex /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1138
    #16 0x125a108 in do_cli /home/hugh/php-5.6.39/sapi/cli/php_cli.c:1038:8
    #17 0x1256f81 in main /home/hugh/php-5.6.39/sapi/cli/php_cli.c:1382:18
    #18 0x7fe2c4e7fb96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #19 0x436129 in _start (/home/hugh/php-5.6.39/sapi/cli/php+0x436129)

0x606000002c38 is located 0 bytes to the right of 56-byte region [0x606000002c00,0x606000002c38)
allocated by thread T0 here:
    #0 0x4eb780 in malloc (/home/hugh/php-5.6.39/sapi/cli/php+0x4eb780)
    #1 0x87e8ff in node_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1120:18
    #2 0x87e8ff in node_new_str /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1498
    #3 0x87e8ff in onig_node_new_str /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1516
    #4 0x812709 in expand_case_fold_string /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3463:9
    #5 0x812709 in setup_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3686
    #6 0x8113e3 in setup_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3677:11
    #7 0x80ec76 in setup_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3666:6
    #8 0x805be8 in onig_compile /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5335:7
    #9 0x82df69 in onig_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5545:7

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/hugh/php-5.6.39/sapi/cli/php+0x4d67d0) in __asan_memcpy
Shadow bytes around the buggy address:
  0x0c0c7fff8530: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff8540: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c0c7fff8550: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8560: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff8570: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
=>0x0c0c7fff8580: 00 00 00 00 00 00 00[fa]fa fa fa fa 00 00 00 00
  0x0c0c7fff8590: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff85a0: fa fa fa fa 00 00 00 00 00 00 00 00 fa fa fa fa
  0x0c0c7fff85b0: 00 00 00 00 00 00 00 00 fa fa fa fa 00 00 00 00
  0x0c0c7fff85c0: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c0c7fff85d0: fa fa fa fa 00 00 00 00 00 00 00 00 fa fa fa fa
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==4295==ABORTING


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports

 [2018-12-30 04:07 UTC] stas@php.net

-PHP Version: 7.1.25 +PHP Version: 5.6.39 -Assigned To: +Assigned To: stas -CVE-ID: +CVE-ID: needed

 [2018-12-30 20:41 UTC] hugh at allthethings dot co dot nz

Verified on 5.6, 7.0. Patch didn't apply cleanly to 7.1 (my bad!). Needs to test against sn->end instead of end in 7.1.25. That also fixes another bug I'm yet to file for 7.1, but still affects 5.6 and 7.0 so will hopefully write that up today

 [2018-12-30 21:09 UTC] hugh at allthethings dot co dot nz

Sorry, I had that file edited, but I found another instance where it could get fixed in compile_length_string_node. Should I just file another bug report for that along with a test case to keep them seperate?

Cheers,

Hugh

 [2018-12-30 22:39 UTC] hugh at allthethings dot co dot nz

#77381 is the new report for the one of the other enclen problems

 [2019-01-07 08:10 UTC] stas@php.net

-Status: Assigned +Status: Closed

 [2019-02-22 22:08 UTC] stas@php.net

-CVE-ID: needed +CVE-ID: 2019-9023