php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72743 Out-of-bound read in php_stream_filter_create
Submitted: 2016-08-03 07:59 UTC Modified: 2016-08-04 06:15 UTC
From: loianhtuan at gmail dot com Assigned:
Status: Closed Package: Filter related
PHP Version: 7.1Git-2016-08-03 (Git) OS:
Private report: No CVE-ID: None
 [2016-08-03 07:59 UTC] loianhtuan at gmail dot com
Description:
------------
Actually OOB read occurs within zend_inline_hash_func when the len is casting from negative integer to size_t.

<snippet main\streams\filter.c:250>
PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval *filterparams, int persistent)
{
	HashTable *filter_hash = (FG(stream_filters) ? FG(stream_filters) : &stream_filters_hash);
	php_stream_filter_factory *factory = NULL;
	php_stream_filter *filter = NULL;
	int n;
	char *period;

	n = (int)strlen(filtername); //n become negative

	if (NULL != (factory = zend_hash_str_find_ptr(filter_hash, filtername, n))) { //parameter expect 64 bit size_t
</snippet>

<snippet Zend/zend_string.h:325>
static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size_t len)
{
	zend_ulong hash = Z_UL(5381);

	/* variant with the hash unrolled eight times */
	for (; len >= 8; len -= 8) { //len here is 64bit and very big
		hash = ((hash << 5) + hash) + *str++;
</snippet>

proposed patch below only patch the filter_create function. zend_inline_hash_func may need a proper check too, but I don't know how:

--- a/main/streams/filter.c
+++ b/main/streams/filter.c
@@ -252,10 +252,10 @@ PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval
        HashTable *filter_hash = (FG(stream_filters) ? FG(stream_filters) : &stream_filters_hash);
        php_stream_filter_factory *factory = NULL;
        php_stream_filter *filter = NULL;
-       int n;
+       size_t n;
        char *period;

-       n = (int)strlen(filtername);
+       n = strlen(filtername);

        if (NULL != (factory = zend_hash_str_find_ptr(filter_hash, filtername, n))) {
                filter = factory->create_filter(filtername, filterparams, persistent);

Test script:
---------------
<?php
ini_set('memory_limit',-1);
$fp = fopen('php://filter/'.str_repeat("A",0x80000000).'/resource=foo', 'w+');
?>

Expected result:
----------------
PHP Warning:  fopen(): unable to locate filter

Actual result:
--------------
Stopped reason: SIGSEGV
0x000000000085ef0f in zend_inline_hash_func (str=0x7ffff5a01001 <error: Cannot access memory at address 0x7ffff5a01001>,
    len=0xfffffffefffff008) at /home/vps/git/php-src/Zend/zend_string.h:338
338                     hash = ((hash << 5) + hash) + *str++;
gdb-peda$ bt
#0  0x000000000085ef0f in zend_inline_hash_func (str=0x7ffff5a01001 <error: Cannot access memory at address 0x7ffff5a01001>,
    len=0xfffffffefffff008) at /home/vps/git/php-src/Zend/zend_string.h:338
#1  0x0000000000864f09 in zend_hash_str_find (ht=0x10cac80 <stream_filters_hash>, str=0x7fff75a00001 'A' <repeats 200 times>...,
    len=0xffffffff80000000) at /home/vps/git/php-src/Zend/zend_hash.c:1967
#2  0x00000000007ddce0 in zend_hash_str_find_ptr (ht=0x10cac80 <stream_filters_hash>, str=0x7fff75a00001 'A' <repeats 200 times>...,
    len=0xffffffff80000000) at /home/vps/git/php-src/Zend/zend_hash.h:717
#3  0x00000000007de76e in php_stream_filter_create (filtername=0x7fff75a00001 'A' <repeats 200 times>..., filterparams=0x0, persistent=0x0)
    at /home/vps/git/php-src/main/streams/filter.c:260
#4  0x000000000078a370 in php_stream_apply_filter_list (stream=0x7ffff685fb40, filterlist=0x7fff75a00001 'A' <repeats 200 times>...,
    read_chain=0x1, write_chain=0x2) at /home/vps/git/php-src/ext/standard/php_fopen_wrapper.c:156
#5  0x000000000078af78 in php_stream_url_wrap_php (wrapper=0x10a6950 <php_stream_php_wrapper>,
    path=0x7ffef580001e "filter/", 'A' <repeats 193 times>..., mode=0x7ffff6858d58 "w+", options=0x0, opened_path=0x0,
    context=0x7ffff6858e00, __php_stream_call_depth=0x1, __zend_filename=0xd723f8 "/home/vps/git/php-src/main/streams/streams.c",
    __zend_lineno=0x809, __zend_orig_filename=0xd550d0 "/home/vps/git/php-src/ext/standard/file.c", __zend_orig_lineno=0x366)
    at /home/vps/git/php-src/ext/standard/php_fopen_wrapper.c:375
#6  0x00000000007da8db in _php_stream_open_wrapper_ex (path=0x7ffef5800018 "php://filter/", 'A' <repeats 187 times>...,
    mode=0x7ffff6858d58 "w+", options=0x8, opened_path=0x0, context=0x7ffff6858e00, __php_stream_call_depth=0x0,
    __zend_filename=0xd550d0 "/home/vps/git/php-src/ext/standard/file.c", __zend_lineno=0x366, __zend_orig_filename=0x0,
    __zend_orig_lineno=0x0) at /home/vps/git/php-src/main/streams/streams.c:2055
#7  0x0000000000730e32 in php_if_fopen (execute_data=0x7ffff6814110, return_value=0x7ffff68140d0)
    at /home/vps/git/php-src/ext/standard/file.c:870
#8  0x0000000000670167 in phar_fopen (execute_data=0x7ffff6814110, return_value=0x7ffff68140d0)
    at /home/vps/git/php-src/ext/phar/func_interceptors.c:427
#9  0x00000000008ae50b in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER () at /home/vps/git/php-src/Zend/zend_vm_execute.h:675
#10 0x00000000008adc2e in execute_ex (ex=0x7ffff6814030) at /home/vps/git/php-src/Zend/zend_vm_execute.h:429
#11 0x00000000008add40 in zend_execute (op_array=0x7ffff687d000, return_value=0x0) at /home/vps/git/php-src/Zend/zend_vm_execute.h:474
#12 0x000000000084e490 in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/vps/git/php-src/Zend/zend.c:1447
#13 0x00000000007b9126 in php_execute_script (primary_file=0x7fffffffd6c0) at /home/vps/git/php-src/main/main.c:2533
#14 0x000000000092d910 in do_cli (argc=0x2, argv=0x10d5770) at /home/vps/git/php-src/sapi/cli/php_cli.c:990
#15 0x000000000092ead4 in main (argc=0x2, argv=0x10d5770) at /home/vps/git/php-src/sapi/cli/php_cli.c:1378
#16 0x00007ffff6faaf45 in __libc_start_main (main=0x92e2cc <main>, argc=0x2, argv=0x7fffffffea68, init=<optimized out>, fini=<optimized out>,
    rtld_fini=<optimized out>, stack_end=0x7fffffffea58) at libc-start.c:287
#17 0x0000000000422ca9 in _start ()

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-08-04 06:15 UTC] stas@php.net
-Type: Security +Type: Bug
 [2016-08-04 11:11 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3800e1cf970ce78c565e98803f799fa50737ecc6
Log: Fixed bug #72743 (Out-of-bound read in php_stream_filter_create)
 [2016-08-04 11:11 UTC] laruence@php.net
-Status: Open +Status: Closed
 [2016-10-17 10:10 UTC] bwoebi@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3800e1cf970ce78c565e98803f799fa50737ecc6
Log: Fixed bug #72743 (Out-of-bound read in php_stream_filter_create)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC