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

================= Bug Report (1/1) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=72750
## Description:
PHP Bug ID: 72750
Summary: wddx_deserialize null dereference
Status: Closed
PHP Version: 5.6.24
Assigned: stas (profile)
CVE-ID: 2016-7130

Description:
Description:
------------
When wddx deserialize tries to parse an invalid base64 binary value, php_base64_decode return NULL. The return value is not checked and used.

https://github.com/php/php-src/blob/master/ext/wddx/wddx.c#L896

                if (!strcmp((char *)name, EL_BINARY)) {
                        zend_string *new_str = php_base64_decode(
                                (unsigned char *)Z_STRVAL(ent1->data), Z_STRLEN(ent1->data));
                        zval_ptr_dtor(&ent1->data);
                        ZVAL_STR(&ent1->data, new_str);
                }


GDB output
----------

gdb -q --args /ramdisk/php-fuzz/phuzzer/php-70//sapi/cli/php -n wdx13.php
No symbol table is loaded.  Use the "file" command.
Breakpoint 1 (__asan_report_error) pending.
Reading symbols from /ramdisk/php-fuzz/phuzzer/php-70//sapi/cli/php...done.
gdb-peda$ r
...
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x5
RBX: 0xffffffff3f0 --> 0x0
RCX: 0x3
RDX: 0x7fffef602dc0 --> 0x7fffef602d20 --> 0x7fffef602e60 --> 0x7fffef602eb0 --> 0x7fffef602f00 --> 0x7fffef602f50 (--> ...)
RSI: 0x0
RDI: 0x5
RBP: 0x7fffffffa090 --> 0x7fffffffa140 --> 0x1
RSP: 0x7fffffff9f50 --> 0x7fffffff9ff0 --> 0x454764685247b6ca
RIP: 0x15c44b0 (<php_wddx_pop_element+2720>:    movzx  edi,BYTE PTR [rsi+0x5])
R8 : 0x0
R9 : 0x0
R10: 0x7fffef601788 --> 0xbed02c8900001406
R11: 0x7fffffffa3b8 --> 0x7fffef66c0a0 --> 0x7fffef601800 --> 0x7fffef658420 --> 0x700000001 --> 0x0
R12: 0x7fffffff9f80 --> 0x41b58ab3
R13: 0x7fffffffa3a0 --> 0x1000000002 --> 0x0
R14: 0x7fffef601780 --> 0x0
R15: 0xffffdec02f0 --> 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x15c449f <php_wddx_pop_element+2703>:       jg     0x15c4570 <php_wddx_pop_element+2912>
   0x15c44a5 <php_wddx_pop_element+2709>:       call   0x428e40 <__asan_report_store1@plt>
   0x15c44aa <php_wddx_pop_element+2714>:       nop    WORD PTR [rax+rax*1+0x0]
=> 0x15c44b0 <php_wddx_pop_element+2720>:       movzx  edi,BYTE PTR [rsi+0x5]
   0x15c44b4 <php_wddx_pop_element+2724>:       mov    rcx,r10
   0x15c44b7 <php_wddx_pop_element+2727>:       and    edi,0x2
   0x15c44ba <php_wddx_pop_element+2730>:       cmp    dil,0x1
   0x15c44be <php_wddx_pop_element+2734>:       sbb    r15d,r15d
[------------------------------------stack-------------------------------------]
0000| 0x7fffffff9f50 --> 0x7fffffff9ff0 --> 0x454764685247b6ca
0008| 0x7fffffff9f58 --> 0x7fffef601788 --> 0xbed02c8900001406
0016| 0x7fffffff9f60 --> 0x7fffef601788 --> 0xbed02c8900001406
0024| 0x7fffffff9f68 --> 0x7fffffffa3b8 --> 0x7fffef66c0a0 --> 0x7fffef601800 --> 0x7fffef658420 --> 0x700000001 (--> ...)
0032| 0x7fffffff9f70 --> 0x0
0040| 0x7fffffff9f78 --> 0x7fffffff9f80 --> 0x41b58ab3
0048| 0x7fffffff9f80 --> 0x41b58ab3
0056| 0x7fffffff9f88 --> 0x2468730 ("3 32 8 3 idx 96 16 5 fname 160 16 6 retval ")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
php_wddx_pop_element (user_data=0x7fffffffa3a0, name=<optimized out>) at /home/operac/php-70/ext/wddx/wddx.c:895
895                             ZVAL_STR(&ent1->data, new_str);

gdb-peda$ bt
#0  php_wddx_pop_element (user_data=0x7fffffffa3a0, name=<optimized out>) at /home/operac/php-70/ext/wddx/wddx.c:895
#1  0x00000000015fe8e1 in _end_element_handler (user=0x7fffef66c140, name=<optimized out>) at /home/operac/php-70/ext/xml/compat.c:219
#2  0x00007ffff569913d in ?? () from /usr/lib/x86_64-linux-gnu/libxml2.so.2
#3  0x00007ffff56a53bd in ?? () from /usr/lib/x86_64-linux-gnu/libxml2.so.2
#4  0x00007ffff56a662b in xmlParseChunk () from /usr/lib/x86_64-linux-gnu/libxml2.so.2
#5  0x0000000001601b8b in php_XML_Parse (parser=parser@entry=0x7fffef66c140,
    data=data@entry=0x7fffef67c018 "<?xml version='1.0'?>\n<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>\n<wddxPacket version='1.0'>\n<header/>\n\t<data>\n        \t<struct>\n", ' ' <repeats 21 times>, "<var name='aBinary'>\n", ' ' <repeats 25 times>, "<bi"..., data_len=data_len@entry=0x141, is_final=is_final@entry=0x1) at /home/operac/php-70/ext/xml/compat.c:596
#6  0x00000000015dda3b in php_wddx_deserialize_ex (value=<optimized out>, vallen=<optimized out>, return_value=return_value@entry=0x7fffef6140d0) at /home/operac/php-70/ext/wddx/wddx.c:1069
#7  0x00000000015deba0 in zif_wddx_deserialize (execute_data=<optimized out>, return_value=0x7fffef6140d0) at /home/operac/php-70/ext/wddx/wddx.c:1283
#8  0x0000000001da38db in ZEND_DO_ICALL_SPEC_HANDLER () at /home/operac/php-70/Zend/zend_vm_execute.h:586
#9  0x0000000001b4c336 in execute_ex (ex=<optimized out>) at /home/operac/php-70/Zend/zend_vm_execute.h:414
#10 0x0000000001df9dc9 in zend_execute (op_array=<optimized out>, return_value=<optimized out>) at /home/operac/php-70/Zend/zend_vm_execute.h:458
#11 0x000000000194764b in zend_execute_scripts (type=type@entry=0x8, retval=retval@entry=0x0, file_count=file_count@entry=0x3) at /home/operac/php-70/Zend/zend.c:1427
#12 0x00000000016b8348 in php_execute_script (primary_file=primary_file@entry=0x7fffffffd030) at /home/operac/php-70/main/main.c:2494
#13 0x0000000001e02127 in do_cli (argc=<optimized out>, argv=<optimized out>) at /home/operac/php-70/sapi/cli/php_cli.c:974
#14 0x0000000000467379 in main (argc=argc@entry=0x3, argv=argv@entry=0x7fffffffe598) at /home/operac/php-70/sapi/cli/php_cli.c:1344
#15 0x00007ffff4ffc830 in __libc_start_main (main=0x466580 <main>, argc=0x3, argv=0x7fffffffe598, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe588) at ../csu/libc-start.c:291
#16 0x0000000000467a49 in _start ()
gdb-peda$ p new_str
$1 = (zend_string *) 0x0
gdb-peda$ p ent1
$2 = (st_entry *) 0x7fffef601780



Test script:
---------------
<?php

$xml = <<< XML
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
<header/>
        <data>
                <struct>
                     <var name='aBinary'>
                         <binary length='11'>\\tYmluYXJRhdGE=</binary>
                     </var>
                 </struct>
        </data>
</wddxPacket>
XML;

$array = wddx_deserialize($xml);

Expected result:
----------------
No crash

Actual result:
--------------
ASAN:SIGSEGV
=================================================================
==29281==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000005 (pc 0x0000015c44b0 bp 0x7ffff23104b0 sp 0x7ffff2310370 T0)
    #0 0x15c44af in php_wddx_pop_element /home/operac/php-70/ext/wddx/wddx.c:885
    #1 0x15fe8e0 in _end_element_handler /home/operac/php-70/ext/xml/compat.c:219
    #2 0x7fe7cd1f613c  (/usr/lib/x86_64-linux-gnu/libxml2.so.2+0x4a13c)
    #3 0x7fe7cd2023bc  (/usr/lib/x86_64-linux-gnu/libxml2.so.2+0x563bc)
    #4 0x7fe7cd20362a in xmlParseChunk (/usr/lib/x86_64-linux-gnu/libxml2.so.2+0x5762a)
    #5 0x1601b8a in php_XML_Parse /home/operac/php-70/ext/xml/compat.c:596
    #6 0x15dda3a in php_wddx_deserialize_ex /home/operac/php-70/ext/wddx/wddx.c:1069
    #7 0x15deb9f in zif_wddx_deserialize /home/operac/php-70/ext/wddx/wddx.c:1283
    #8 0x1da38da in ZEND_DO_ICALL_SPEC_HANDLER /home/operac/php-70/Zend/zend_vm_execute.h:586
    #9 0x1b4c335 in execute_ex /home/operac/php-70/Zend/zend_vm_execute.h:414
    #10 0x1df9dc8 in zend_execute /home/operac/php-70/Zend/zend_vm_execute.h:458
    #11 0x194764a in zend_execute_scripts /home/operac/php-70/Zend/zend.c:1427
    #12 0x16b8347 in php_execute_script /home/operac/php-70/main/main.c:2494
    #13 0x1e02126 in do_cli /home/operac/php-70/sapi/cli/php_cli.c:974
    #14 0x467378 in main /home/operac/php-70/sapi/cli/php_cli.c:1344
    #15 0x7fe7ccb5982f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #16 0x467a48 in _start (/ramdisk/php-fuzz/phuzzer/php-70/sapi/cli/php+0x467a48)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/operac/php-70/ext/wddx/wddx.c:885 php_wddx_pop_element
==29281==ABORTING

Comments:

[Comment 1] [2016-08-07 23:27 UTC] stas@php.net
Fix in https://gist.github.com/f149d1a8226fb48d6a59911d7f08f617 and in security repo as 6930a1d12c47aa1d2675837852910d177b0ceb11. Please verify.
Links: https://gist.github.com/f149d1a8226fb48d6a59911d7f08f617

[Comment 2] [2016-08-09 22:47 UTC] fernando at null-life dot com
Works OK. Thanks.

$ /home/operac/build2/bin/php -n 72750.php 
array(1) {
  ["aBinary"]=>
  string(0) ""
}

[Comment 3] [2016-08-11 06:11 UTC] fernando at null-life dot com
Related To: Bug #72790
Links: https://bugs.php.net/bug.php?id=72790

[Comment 13] [2017-08-13 19:31 UTC] cmb@php.net
Related To: Bug #68811
Links: https://bugs.php.net/bug.php?id=68811

Commit References:
6930a1d12c47aa1d2675837852910d177b0ceb11

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 e018ff094f8505ea77f881ba11176e3ad0b4863e
WORKDIR $SRC/php-src
COPY build.sh $SRC/

Additional files: