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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: loianhtuan at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC