Project: php-src (php/php-src), language: c++
Vulnerability instance: php.cve-2020-7060
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=79037
## Description:
PHP Bug ID: 79037
Summary: global buffer-overflow in `mbfl_filt_conv_big5_wchar`
Status: Closed
PHP Version: 7.4Git-2019-12-26 (Git)
Assigned: stas (profile)
CVE-ID: 2020-7060

Description:
Description:
------------
There is an Undefined Behaviour in libmbfl at `mbfl_filt_conv_big5_wchar` function which leads to a buffer overflow on `cp950_pua_tbl` global variable.

./php --version
PHP 7.4.2-dev (cli) (built: Dec 26 2019 15:32:36) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies


Compiled with:
CC=clang-6.0  CFLAGS="-fPIE -fsanitize=address,undefined -g" LDFLAGS="-pie" ./configure --enable-exif --enable-mbstring

Test script:
---------------
./php -r 'mb_decode_mimeheader(file_get_contents("php://stdin"));' < global-overflow-cp950_pua_tbl.poc

You can download the poc from this repository.

https://github.com/gaintcome/fuzz-php/blob/master/poc/mbstrings/global-overflow-cp950_pua_tbl.poc



Actual result:
--------------
php-src/ext/mbstring/libmbfl/filters/mbfilter_big5.c:212:11: runtime error: index 5 out of bounds for type 'unsigned short [5][4]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior php-src/ext/mbstring/libmbfl/filters/mbfilter_big5.c:212:11 in 
=================================================================
==32013==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000004f80a4c at pc 0x00000126177b bp 0x7fffffff9540 sp 0x7fffffff9538
READ of size 2 at 0x000004f80a4c thread T0
    #0 0x126177a in mbfl_filt_conv_big5_wchar php-src/ext/mbstring/libmbfl/filters/mbfilter_big5.c:212:11
    #1 0x13b836f in mbfl_filter_output_pipe php-src/ext/mbstring/libmbfl/mbfl/mbfl_filter_output.c:41:9
    #2 0x12fa512 in mbfl_filt_conv_qprintdec php-src/ext/mbstring/libmbfl/filters/mbfilter_qprint.c:218:4
    #3 0x13a1155 in mime_header_decoder_collector php-src/ext/mbstring/libmbfl/mbfl/mbfilter.c:2285:4
    #4 0x13a33a3 in mbfl_mime_header_decode php-src/ext/mbstring/libmbfl/mbfl/mbfilter.c:2451:3
    #5 0x11de031 in zif_mb_decode_mimeheader php-src/ext/mbstring/mbstring.c:3735:8
    #6 0x39858b1 in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER php-src/Zend/zend_vm_execute.h:1269:2
    #7 0x30cfe4e in execute_ex php-src/Zend/zend_vm_execute.h:53611:7
    #8 0x30d2f86 in zend_execute php-src/Zend/zend_vm_execute.h:57913:2
    #9 0x2a45235 in zend_eval_stringl php-src/Zend/zend_execute_API.c:1086:4
    #10 0x2a469f0 in zend_eval_stringl_ex php-src/Zend/zend_execute_API.c:1127:11
    #11 0x2a46bd0 in zend_eval_string_ex php-src/Zend/zend_execute_API.c:1138:9
    #12 0x3cbd3aa in do_cli php-src/sapi/cli/php_cli.c:992:8
    #13 0x3cb8471 in main php-src/sapi/cli/php_cli.c:1352:18
    #14 0x7ffff619882f in __libc_start_main /build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:291
    #15 0x441d28 in _start (php-src/sapi/cli/php+0x441d28)

0x000004f80a4c is located 4 bytes to the right of global variable 'cp950_pua_tbl' defined in 'php-src/ext/mbstring/libmbfl/filters/mbfilter_big5.c:137:23' (0x4f80a20) of size 40
SUMMARY: AddressSanitizer: global-buffer-overflow php-src/ext/mbstring/libmbfl/filters/mbfilter_big5.c:212:11 in mbfl_filt_conv_big5_wchar
Shadow bytes around the buggy address:
  0x0000809e80f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000809e8100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000809e8110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000809e8120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000809e8130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0000809e8140: 00 00 00 00 00 00 00 00 00[f9]f9 f9 f9 f9 f9 f9
  0x0000809e8150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000809e8160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000809e8170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000809e8180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000809e8190: 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
  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
==32013==ABORTING

Comments:

[Comment 1] [2019-12-28 12:03 UTC] cmb@php.net
Thanks for reporting!

Possible fix including a test case:
<https://gist.github.com/cmb69/951f7404fda6d71400ac63dcbe3b1463>.
Links: https://gist.github.com/cmb69/951f7404fda6d71400ac63dcbe3b1463

[Comment 2] [2019-12-30 04:50 UTC] reza at iseclab dot org
Thanks for the fix. I can confirm I don't see the issue after applying the patch.

[Comment 3] [2019-12-30 15:27 UTC] cmb@php.net
Thanks for verifying!

@nikic, could you please have a look?

[Comment 4] [2019-12-30 15:44 UTC] nikic@php.net
This doesn't look right to me. The is_in_cp950_pua() check should be making sure that the table entry exists. Why doesn't it?

[Comment 5] [2019-12-30 15:52 UTC] nikic@php.net
Okay, I see the issue. The is_in_cp950_pua() code does a check for c > 0x39, while the table entry starts at 0x40 ... which would be fine if this were decimals, but this is hex, so there's still 0x3a..0x3f between there!

[Comment 6] [2019-12-30 15:59 UTC] nikic@php.net
Here is an alternative patch and reduced test-case: https://gist.github.com/nikic/f52bd4b3c9ab12e5cee1eb89ae13f351
Links: https://gist.github.com/nikic/f52bd4b3c9ab12e5cee1eb89ae13f351

[Comment 7] [2019-12-30 17:49 UTC] cmb@php.net
Ah, much better than my patch.  Can we assign to Stas?

[Comment 8] [2020-01-05 01:11 UTC] reza at iseclab dot org
Do you assign a CVE to this?

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
autoreconf -vfi
./configure
make -j$(nproc)
export ONIG_CFLAGS="-I$PWD/oniguruma/src"
export ONIG_LIBS="-L$PWD/oniguruma/src/.libs -l:libonig.a"
export CFLAGS="$CFLAGS -fno-sanitize=object-size"
export CXXFLAGS="$CXXFLAGS -fno-sanitize=object-size"
./buildconf --force
./configure \
        --disable-all \
        --enable-option-checking=fatal \
        --enable-json \
        --enable-exif \
        --enable-mbstring \
        --without-pcre-jit \
        --disable-phpdbg \
        --disable-cgi \
        --with-pic

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y autoconf automake libtool bison re2c pkg-config
RUN apt-get install -y autoconf automake libtool bison re2c pkg-config
RUN git clone https://github.com/php/php-src php-src
RUN git -C php-src checkout 525e494fe5b65f05d62fe5a7bacd1bd8cd72ed1e
WORKDIR $SRC/php-src
COPY build.sh $SRC/

Additional files:
filename: cosmic.list
content: deb http://archive.ubuntu.com/ubuntu/ cosmic universe