Bug #76047 [Asn->Csd]: Use-after-free when accessing already destructed backtrace arguments
| From: | nikic@php.net | Date: | Fri, 31 Jan 2020 09:31:26 +0000 |
| Subject: | Bug #76047 [Asn->Csd]: Use-after-free when accessing already destructed backtrace arguments | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-225273@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=76047&edit=1
ID: 76047
Updated by: nikic@php.net
Reported by: kenashkov at gmail dot com
Summary: Use-after-free when accessing already destructed
backtrace arguments
-Status: Assigned
+Status: Closed
Type: Bug
Package: Reproducible crash
Operating System: CentOS Linux release 7.0.1406 (C
PHP Version: 7.2.3
Assigned To: nikic
Block user comment: Y
Private report: N
New Comment:
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ef1e4891b47949c8dc0f9482eef9454a0ecdfa1d
Log: Fix bug #76047
Previous Comments:
------------------------------------------------------------------------
[2020-01-30 21:41:05] rasmus@php.net
https://github.com/mm0r1/exploits/tree/master/php7-backtrace-bypass
------------------------------------------------------------------------
[2020-01-30 20:50:40] stas@php.net
Could you please specify what you mean by "exploiting it in the wild"? what exactly is
being exploited? I see that the specific code can trigger UAF, but there's no security issue
there, it's just a regular crash. Are you saying there's some way to remotely exploit this
problem on an arbitrary (or common) PHP code? If so, could you refer to a specific example of that?
------------------------------------------------------------------------
[2020-01-30 19:26:55] nikic@php.net
Reduced test case:
<?php
class Vuln {
public $a;
public function __destruct() {
global $backtrace;
unset($this->a);
$backtrace = (new Exception)->getTrace();
}
}
function trigger_uaf($arg) {
$arg = str_shuffle(str_repeat('A', 79));
$vuln = new Vuln();
$vuln->a = $arg;
}
trigger_uaf('x');
Valgrind:
==19523== Invalid read of size 4
==19523== at 0x95ACE4: zend_gc_addref (zend_types.h:1035)
==19523== by 0x95AE04: zval_addref_p (zend_types.h:1070)
==19523== by 0x963E3B: debug_backtrace_get_args (zend_builtin_functions.c:2156)
==19523== by 0x9654C8: zend_fetch_debug_backtrace (zend_builtin_functions.c:2551)
==19523== by 0x96CA84: zend_default_exception_new_ex (zend_exceptions.c:215)
==19523== by 0x96CD2B: zend_default_exception_new (zend_exceptions.c:246)
==19523== by 0x944F5E: _object_and_properties_init (zend_API.c:1417)
==19523== by 0x944FCC: object_init_ex (zend_API.c:1431)
==19523== by 0x9C097F: ZEND_NEW_SPEC_CONST_UNUSED_HANDLER (zend_vm_execute.h:9225)
==19523== by 0xA1797F: execute_ex (zend_vm_execute.h:54571)
==19523== by 0x924E0A: zend_call_function (zend_execute_API.c:812)
==19523== by 0x98E5EA: zend_objects_destroy_object (zend_objects.c:179)
==19523== Address 0x124f1d40 is 0 bytes inside a block of size 104 free'd
==19523== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19523== by 0x902F35: _efree_custom (zend_alloc.c:2425)
==19523== by 0x903080: _efree (zend_alloc.c:2545)
==19523== by 0x939CFC: zend_string_destroy (zend_variables.c:67)
==19523== by 0x939BFB: rc_dtor_func (zend_variables.c:57)
==19523== by 0x939B7E: i_zval_ptr_dtor (zend_variables.h:44)
==19523== by 0x939D90: zval_ptr_dtor (zend_variables.c:84)
==19523== by 0x992DB7: zend_std_unset_property (zend_object_handlers.c:1127)
==19523== by 0x9F4460: ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER (zend_vm_execute.h:32155)
==19523== by 0xA19883: execute_ex (zend_vm_execute.h:56539)
==19523== by 0x924E0A: zend_call_function (zend_execute_API.c:812)
==19523== by 0x98E5EA: zend_objects_destroy_object (zend_objects.c:179)
==19523== Block was alloc'd at
==19523== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19523== by 0x903F80: __zend_malloc (zend_alloc.c:2975)
==19523== by 0x902EC8: _malloc_custom (zend_alloc.c:2416)
==19523== by 0x903006: _emalloc (zend_alloc.c:2535)
==19523== by 0x78B0ED: zend_string_alloc (zend_string.h:133)
==19523== by 0x78B235: zend_string_init (zend_string.h:155)
==19523== by 0x7A9CAF: zif_str_shuffle (string.c:6096)
==19523== by 0x9B10AC: ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER (zend_vm_execute.h:1314)
==19523== by 0xA16DF9: execute_ex (zend_vm_execute.h:53797)
==19523== by 0xA1AF38: zend_execute (zend_vm_execute.h:57913)
==19523== by 0x93E39D: zend_execute_scripts (zend.c:1665)
==19523== by 0x89FE54: php_execute_script (main.c:2617)
------------------------------------------------------------------------
[2020-01-30 18:22:21] theodore at phpexperts dot pro
Heads up! Someone posted an active exploit against this bug on GitHub in late October 2019 and then
posted it on reddit today, 2019-01-29.
This bug needs to be fixed ASAP since it affects PHP 7.0-7.4 and people are already exploiting it in
the wild.
The person who uploaded the exploit, without notifying you guys, really needs to be publicly shamed.
This is reprehensible and illegal in the United States.
* https://github.com/mm0r1/exploits/tree/master/php7-backtrace-bypass
* https://www.reddit.com/r/PHP/comments/ew83rx/php_7074_disable_functions_bypass_0day_poc/
------------------------------------------------------------------------
[2018-03-14 10:21:15] kenashkov at gmail dot com
As suggested by Niki, I can confirm that the bug is related to an exception in a destructor. The
exception is only created (not thrown) for the purpose of preserving the backtrace for other use if
need arises (it may be thrown at a much later stage)... And as suggested it is extremely probable
that the generated backtrace at the exception creation contains references to destroyed arguments.
We still dont have a short reproduction case.
Is there are way to still create an exception in this case?
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=76047
--
Edit this bug report at https://bugs.php.net/bug.php?id=76047&edit=1