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

================= Bug Report (1/1) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=77380
## Description:
PHP Bug ID: 77380
Summary: Global out of bounds read in xmlrpc base64 code
Status: Closed
PHP Version: 5.6.39
Assigned: stas (profile)
CVE-ID: 2019-9024

Description:
Description:
------------
The sample code below will cause a global out of bounds buffer read.

This seems to happen due to a bad base64 input.

It seems that in ext/xmlrpc/libxmlrpc/base64.c there's a second base64 implementation in the PHP code. I was quite surprised by this and it's probably not desirable and should use the "normal" base64 code in PHP that's probably better tested.

ASAN error:
==27771==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000030ee593 at pc 0x0000015d3c46 bp 0x7ffcf5d8fb70 sp 0x7ffcf5d8fb68
READ of size 1 at 0x0000030ee593 thread T0
    #0 0x15d3c45 in base64_decode_xmlrpc /f/php/php-7.2.13/ext/xmlrpc/libxmlrpc/base64.c:172:10
    #1 0x15d9bda in xml_element_to_XMLRPC_REQUEST_worker /f/php/php-7.2.13/ext/xmlrpc/libxmlrpc/xml_to_xmlrpc.c:139:10
    #2 0x15d9e8c in xml_element_to_XMLRPC_REQUEST /f/php/php-7.2.13/ext/xmlrpc/libxmlrpc/xml_to_xmlrpc.c:181:45
    #3 0x15e4502 in XMLRPC_REQUEST_FromXML /f/php/php-7.2.13/ext/xmlrpc/libxmlrpc/xmlrpc.c:823:13
    #4 0x15c5b5b in decode_request_worker /f/php/php-7.2.13/ext/xmlrpc/xmlrpc-epi-php.c:763:13
    #5 0x15c5b5b in zif_xmlrpc_decode /f/php/php-7.2.13/ext/xmlrpc/xmlrpc-epi-php.c:818
    #6 0x1bc89b8 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /f/php/php-7.2.13/Zend/zend_vm_execute.h:617:2
    #7 0x1981d2c in execute_ex /f/php/php-7.2.13/Zend/zend_vm_execute.h:59739:7
    #8 0x1982615 in zend_execute /f/php/php-7.2.13/Zend/zend_vm_execute.h:63776:2
    #9 0x17bef41 in zend_eval_stringl /f/php/php-7.2.13/Zend/zend_execute_API.c:1083:4
    #10 0x17bf87f in zend_eval_stringl_ex /f/php/php-7.2.13/Zend/zend_execute_API.c:1124:11
    #11 0x17bf87f in zend_eval_string_ex /f/php/php-7.2.13/Zend/zend_execute_API.c:1135
    #12 0x1d024b6 in do_cli /f/php/php-7.2.13/sapi/cli/php_cli.c:1044:8
    #13 0x1cffbd2 in main /f/php/php-7.2.13/sapi/cli/php_cli.c:1406:18
    #14 0x7fd1a18f94ea in __libc_start_main (/lib64/libc.so.6+0x244ea)
    #15 0x423dc9 in _start (/r/php/php+0x423dc9)

0x0000030ee593 is located 45 bytes to the left of global variable 'get_type_str_mapping.first' defined in '/f/php/php-7.2.13/ext/xmlrpc/xmlrpc-epi-php.c' (0x30ee5c0) of size 1
  'get_type_str_mapping.first' is ascii string ''
0x0000030ee593 is located 11 bytes to the right of global variable 'str_mapping' defined in '/f/php/php-7.2.13/ext/xmlrpc/xmlrpc-epi-php.c:1209:21' (0x30ee520) of size 104


Test script:
---------------
$a=xmlrpc_decode(base64_decode("PGJhc2U2ND7CkzwvYmFzZTY0Pgo="));

Comments:

[Comment 1] [2018-12-31 15:15 UTC] cmb@php.net
> It seems that in ext/xmlrpc/libxmlrpc/base64.c there's a second
> base64 implementation in the PHP code.

ext/xmlrpc/libxmlrpc contains a modified libxmlrpc-epi[1], but we
still allow to use the (unmaintained) upstream library instead.

[1] <http://xmlrpc-epi.sourceforge.net/>
Links: http://xmlrpc-epi.sourceforge.net/

[Comment 2] [2019-01-02 00:58 UTC] stas@php.net
The problem may be in this code:

 for (i = 0; i < 4; i++) {
            int c;
            c = *(source++);

...
            if (dtable[c] & 0x80) {
...

So c is declared as signed int (converted from signed char), but used as an array index. This leads to bad access to any value of c which is interpreted as a negative (which shouldn't happen in proper base64 but...). So making it unsigned should fix it.

[Comment 3] [2019-01-02 01:17 UTC] stas@php.net
Fix security repo as d4f58f35c369e5831fad27401cd9fe0d5aef62d5 and in https://gist.github.com/smalyshev/498c26052eb24b763888cf0fce5decd5

Please verify. 

I am not sure this can actually cause a security issue, since the range of memory it can read is limited and fixed, but maybe it's possible. So I guess it needs a CVE.
Links: https://gist.github.com/smalyshev/498c26052eb24b763888cf0fce5decd5

Commit References:
d4f58f35c369e5831fad27401cd9fe0d5aef62d5

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
./buildconf --force
./configure \
        --enable-option-checking=fatal \
        --disable-libxml \
        --disable-dom \
        --disable-simplexml \
        --disable-xml \
        --disable-xmlreader \
        --disable-xmlwriter \
        --without-pear \
        --enable-exif \
        --disable-phpdbg \
        --disable-cgi
make -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool bison re2c make ca-certificates curl xz-utils dpkg-dev file libc-dev pkg-config libcurl4-openssl-dev libedit-dev libsqlite3-dev libssl-dev zlib1g-dev
RUN git clone https://github.com/php/php-src php-src
RUN git -C php-src checkout 05fb10165081cb4fb55a9943b44cab62c627db7a
WORKDIR $SRC/php-src
COPY build.sh $SRC/

Additional files: