php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73876 Crash when exporting **= in expansion of assign op
Submitted: 2017-01-05 22:02 UTC Modified: 2017-01-08 20:09 UTC
From: kshah at fortinet dot com Assigned: ab (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 7.1.0 OS: Windows 7 SP1
Private report: No CVE-ID: None
 [2017-01-05 22:02 UTC] kshah at fortinet dot com
Description:
------------
Description:
------------
There exists a DEP Violation Vulnerability leading to Arbitrary Code Execution within the latest PHP-Win client.

In order to reproduce this issue, please do the following.
1) Enable Full page heap using the command "gflags /p /enable php-win.exe /full" without the double quotes in an elevated command prompt.
2) Run the PoC.php test script using the php-win cli client under windbg.
3) Check the debug output in windbg.



Test script:
---------------
<?php

assert_options(ASSERT_WARNING);
assert(false &รข ($a **= 2));


Actual result:
--------------
Microsoft (R) Windows Debugger Version 6.11.0001.404 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: C:\php-7.1.0-nts-Win32-VC14-x86\php-win.exe "C:\PoC.php"
Symbol search path is: *** Invalid ***
****************************************************************************
* Symbol loading may be unreliable without a symbol search path.           *
* Use .symfix to have the debugger choose a symbol path.                   *
* After setting your symbol path, use .reload to refresh symbol locations. *
****************************************************************************
Executable search path is: 
ModLoad: 00000000`00d80000 00000000`00d8c000   php-win.exe
ModLoad: 00000000`77730000 00000000`778da000   ntdll.dll
ModLoad: 00000000`77910000 00000000`77a90000   ntdll32.dll
ModLoad: 00000000`00080000 00000000`000ee000   C:\Windows\system32\verifier.dll
Page heap: pid 0x2704: page heap enabled with flags 0x3.
ModLoad: 00000000`73960000 00000000`7399f000   C:\Windows\SYSTEM32\wow64.dll
ModLoad: 00000000`73900000 00000000`7395c000   C:\Windows\SYSTEM32\wow64win.dll
ModLoad: 00000000`738f0000 00000000`738f8000   C:\Windows\SYSTEM32\wow64cpu.dll
(2704.2088): Break instruction exception - code 80000003 (first chance)
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll - 
ntdll!CsrSetPriorityClass+0x40:
00000000`777d7980 cc              int     3
0:000> .symfix+; .reload /f
Reloading current modules
..*** ERROR: Symbol file could not be found.  Defaulted to export symbols for php-win.exe - 
.....
0:000> g
ModLoad: 00000000`77510000 00000000`7762f000   WOW64_IMAGE_SECTION
ModLoad: 00000000`764e0000 00000000`765f0000   WOW64_IMAGE_SECTION
ModLoad: 00000000`77510000 00000000`7762f000   NOT_AN_IMAGE
ModLoad: 00000000`77630000 00000000`7772a000   NOT_AN_IMAGE
ModLoad: 00000000`6de30000 00000000`6de90000   C:\Windows\syswow64\verifier.dll
Page heap: pid 0x2704: page heap enabled with flags 0x3.
ModLoad: 00000000`764e0000 00000000`765f0000   C:\Windows\syswow64\kernel32.dll
ModLoad: 00000000`754c0000 00000000`75507000   C:\Windows\syswow64\KERNELBASE.dll
ModLoad: 00000000`5a760000 00000000`5ae60000   C:\php-7.1.0-nts-Win32-VC14-x86\php7.dll
ModLoad: 00000000`77460000 00000000`77501000   C:\Windows\syswow64\ADVAPI32.dll
ModLoad: 00000000`77340000 00000000`773ec000   C:\Windows\syswow64\msvcrt.dll
ModLoad: 00000000`75ea0000 00000000`75eb9000   C:\Windows\SysWOW64\sechost.dll
ModLoad: 00000000`75270000 00000000`75360000   C:\Windows\syswow64\RPCRT4.dll
ModLoad: 00000000`75200000 00000000`75260000   C:\Windows\syswow64\SspiCli.dll
ModLoad: 00000000`751f0000 00000000`751fc000   C:\Windows\syswow64\CRYPTBASE.dll
ModLoad: 00000000`76280000 00000000`762b5000   C:\Windows\syswow64\WS2_32.dll
ModLoad: 00000000`76270000 00000000`76276000   C:\Windows\syswow64\NSI.dll
ModLoad: 00000000`75360000 00000000`754bd000   C:\Windows\syswow64\ole32.dll
ModLoad: 00000000`75de0000 00000000`75e70000   C:\Windows\syswow64\GDI32.dll
ModLoad: 00000000`75f60000 00000000`76060000   C:\Windows\syswow64\USER32.dll
ModLoad: 00000000`772f0000 00000000`772fa000   C:\Windows\syswow64\LPK.dll
ModLoad: 00000000`75520000 00000000`755bd000   C:\Windows\syswow64\USP10.dll
ModLoad: 00000000`72dd0000 00000000`72e14000   C:\Windows\SysWOW64\DNSAPI.dll
ModLoad: 00000000`772d0000 00000000`772d5000   C:\Windows\syswow64\PSAPI.DLL
ModLoad: 00000000`6f490000 00000000`6f4a5000   C:\Windows\SysWOW64\VCRUNTIME140.dll
ModLoad: 00000000`6f590000 00000000`6f594000   C:\Windows\SysWOW64\api-ms-win-crt-runtime-l1-1-0.dll
ModLoad: 00000000`687a0000 00000000`68881000   C:\Windows\SysWOW64\ucrtbase.DLL
ModLoad: 00000000`6f580000 00000000`6f583000   C:\Windows\SysWOW64\api-ms-win-core-timezone-l1-1-0.dll
ModLoad: 00000000`6f480000 00000000`6f483000   C:\Windows\SysWOW64\api-ms-win-core-file-l2-1-0.dll
ModLoad: 00000000`6ef10000 00000000`6ef13000   C:\Windows\SysWOW64\api-ms-win-core-localization-l1-2-0.dll
ModLoad: 00000000`70e90000 00000000`70e93000   C:\Windows\SysWOW64\api-ms-win-core-synch-l1-2-0.dll
ModLoad: 00000000`6e960000 00000000`6e963000   C:\Windows\SysWOW64\api-ms-win-core-processthreads-l1-1-1.dll
ModLoad: 00000000`6e950000 00000000`6e953000   C:\Windows\SysWOW64\api-ms-win-core-file-l1-2-0.dll
ModLoad: 00000000`6e940000 00000000`6e944000   C:\Windows\SysWOW64\api-ms-win-crt-string-l1-1-0.dll
ModLoad: 00000000`6e460000 00000000`6e463000   C:\Windows\SysWOW64\api-ms-win-crt-heap-l1-1-0.dll
ModLoad: 00000000`6e440000 00000000`6e444000   C:\Windows\SysWOW64\api-ms-win-crt-stdio-l1-1-0.dll
ModLoad: 00000000`6e430000 00000000`6e434000   C:\Windows\SysWOW64\api-ms-win-crt-convert-l1-1-0.dll
ModLoad: 00000000`6df90000 00000000`6df95000   C:\Windows\SysWOW64\api-ms-win-crt-math-l1-1-0.dll
ModLoad: 00000000`6de20000 00000000`6de23000   C:\Windows\SysWOW64\api-ms-win-crt-environment-l1-1-0.dll
ModLoad: 00000000`6de10000 00000000`6de13000   C:\Windows\SysWOW64\api-ms-win-crt-locale-l1-1-0.dll
ModLoad: 00000000`6c2d0000 00000000`6c2d3000   C:\Windows\SysWOW64\api-ms-win-crt-filesystem-l1-1-0.dll
ModLoad: 00000000`6c2c0000 00000000`6c2c3000   C:\Windows\SysWOW64\api-ms-win-crt-time-l1-1-0.dll
ModLoad: 00000000`68790000 00000000`68793000   C:\Windows\SysWOW64\api-ms-win-crt-utility-l1-1-0.dll
(2704.2088): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll32!LdrpDoDebuggerBreak+0x2c:
779b0ed4 cc              int     3
0:000:x86> g
ModLoad: 77400000 77460000   C:\Windows\SysWOW64\IMM32.DLL
ModLoad: 75d10000 75ddd000   C:\Windows\syswow64\MSCTF.dll
(2704.2088): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
e8cb8bd6 ??              ???
0:000:x86> g
(2704.2088): Access violation - code c0000005 (!!! second chance !!!)
e8cb8bd6 ??              ???
0:000:x86> r
eax=00000090 ebx=04f3c1bc ecx=00000207 edx=00000008 esi=0b26b138 edi=00000000
eip=e8cb8bd6 esp=04f3c084 ebp=00000001 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
e8cb8bd6 ??              ???
0:000:x86> kb
ChildEBP RetAddr  Args to Child              
WARNING: Frame IP not in any known module. Following frames may be wrong.
04f3c080 0b26b154 0b26b148 00000000 04f3c1bc 0xe8cb8bd6
04f3c0ac 687cf7c6 5aab3b41 00000014 00000000 0xb26b154
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Users\Kush_Test\Desktop\php-7.1.0-nts-Win32-VC14-x86\php7.dll - 
04f3c0d0 5aab1cd3 00000001 00000014 00000000 ucrtbase!__crt_state_management::get_current_state_index+0x66
04f3c110 5aab2033 00000000 00000000 000000a1 php7!zend_ast_export+0x1403
04f3c1c4 5aac199c 5acffc74 0b26b178 5acfd868 php7!zend_ast_export+0x1763
04f3c204 5a7772e9 5aa83992 0b2012d0 0c79efc8 php7!zend_assert_valid_class_name+0x10bc
04f3c208 5aa83992 0b2012d0 0c79efc8 0c79efc8 php7!zend_string_tolower+0x269
04f3c224 5a776ec1 0b26b188 0c79efc8 00000000 php7!libiconv_set_relocation_prefix+0x1da72
04f3c2f0 5a775c4d 00000001 0b26b010 0b26b020 php7!zend_check_magic_method_implementation+0x13b1
04f3c308 5a775c9d 04f3c370 5ae2100c 0b273000 php7!zend_check_magic_method_implementation+0x13d
04f3c320 5a789439 00000000 04f3ef94 04f3c43c php7!zend_check_magic_method_implementation+0x18d
04f3c3ac 5a789300 5a789312 00000000 5a7892e0 php7!compile_file+0x159
04f3c3b0 5a789312 00000000 5a7892e0 00000000 php7!compile_file+0x20
04f3c43c 5a94b80f 04f3ef94 00000008 00000001 php7!compile_file+0x32
04f3c4ec 5a94b7ea 04f3f958 00000000 56433230 php7!php_pdo_free_statement+0x1230f
00000000 00000000 00000000 00000000 00000000 php7!php_pdo_free_statement+0x122ea

0:000:x86> !exploitable -v

!exploitable 1.6.0.0
HostMachine\HostUser
Executing Processor Architecture is x86
Debuggee is in User Mode
Debuggee is a live user mode debugging session on the local machine
Event Type: Exception
Exception Faulting Address: 0xe8cb8bd6
Second Chance Exception Type: STATUS_ACCESS_VIOLATION (0xC0000005)
Exception Sub-Type: Data Execution Protection (DEP) Violation

Exception Hash (Major/Minor): 0xcbe3bf09.0x1504bb6e

 Hash Usage : Stack Trace:
Major+Minor : Unknown
Major+Minor : Unknown
Major+Minor : ucrtbase!__crt_state_management::get_current_state_index+0x66
Major+Minor : php7!zend_ast_export+0x1403
Major+Minor : php7!zend_ast_export+0x1763
Minor       : php7!zend_assert_valid_class_name+0x10bc
Minor       : php7!zend_string_tolower+0x269
Minor       : php7!libiconv_set_relocation_prefix+0x1da72
Minor       : php7!zend_check_magic_method_implementation+0x13b1
Minor       : php7!zend_check_magic_method_implementation+0x13d
Minor       : php7!zend_check_magic_method_implementation+0x18d
Minor       : php7!compile_file+0x159
Minor       : php7!compile_file+0x20
Minor       : php7!compile_file+0x32
Minor       : php7!php_pdo_free_statement+0x1230f
Minor       : php7!php_pdo_free_statement+0x122ea
Instruction Address: 0xffffffffe8cb8bd6

Description: Data Execution Prevention Violation
Short Description: DEPViolation
Exploitability Classification: EXPLOITABLE
Recommended Bug Title: Exploitable - Data Execution Prevention Violation starting at Unknown Symbol @ 0xffffffffe8cb8bd6 called from ucrtbase!__crt_state_management::get_current_state_index+0x0000000000000066 (Hash=0xcbe3bf09.0x1504bb6e)

User mode DEP access violations are exploitable.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-01-05 23:39 UTC] stas@php.net
-Summary: FG-VD-17-002 Fortinet discovers DEP Violation Vulnerability in PHP +Summary: Crash when calling undefined function from assert() on Windows -Type: Security +Type: Bug
 [2017-01-05 23:39 UTC] stas@php.net
Not a security issue.

It would be helpful if PHP was compiled with debug information (such as line numbers) so we could see where the problem is.
 [2017-01-06 01:28 UTC] kshah at fortinet dot com
-Type: Bug +Type: Security -Private report: No +Private report: Yes
 [2017-01-06 01:28 UTC] kshah at fortinet dot com
Not a security issue? How?

A DEP Violation is caused when we run the following PHP test script which thereby tries to write to NX bits on a system. 

This is most definitely a big security issue.

Yes, I agree, PHP should be compiled with debug information (such as line numbers), but in this case the test binary was provided by PHP website which might have missed out on it.
 [2017-01-06 17:19 UTC] cmb@php.net
-Package: *General Issues +Package: Scripting Engine problem
 [2017-01-06 17:19 UTC] cmb@php.net
I can reproduce the issue with the current PHP-7.1 branch (commit
c50f61b9), and get the following backtrace:

 	ucrtbased.dll!00007ffeb7da1a05()	Unknown
 	ucrtbased.dll!00007ffeb7da1ba3()	Unknown
 	ucrtbased.dll!00007ffeb7dc2b7d()	Unknown
 	ucrtbased.dll!00007ffeb7dc8765()	Unknown
 	ucrtbased.dll!00007ffeb7dc8287()	Unknown
 	ucrtbased.dll!00007ffeb7dc6318()	Unknown
 	ucrtbased.dll!00007ffeb7dc8cef()	Unknown
>	php7ts_debug.dll!zend_ast_export_ex(smart_str * str, _zend_ast * ast, int priority, int indent) Line 1346	C
 	php7ts_debug.dll!zend_ast_export_list(smart_str * str, _zend_ast_list * list, int separator, int priority, int indent) Line 754	C
 	php7ts_debug.dll!zend_ast_export_ex(smart_str * str, _zend_ast * ast, int priority, int indent) Line 1112	C
 	php7ts_debug.dll!zend_ast_export_ex(smart_str * str, _zend_ast * ast, int priority, int indent) Line 1323	C
 	php7ts_debug.dll!zend_ast_export_ex(smart_str * str, _zend_ast * ast, int priority, int indent) Line 1661	C
 	php7ts_debug.dll!zend_ast_export(const char * prefix, _zend_ast * ast, const char * suffix) Line 1713	C
 	php7ts_debug.dll!zend_compile_assert(_znode * result, _zend_ast_list * args, _zend_string * name, _zend_function * fbc) Line 3633	C
 	php7ts_debug.dll!zend_try_compile_special_func(_znode * result, _zend_string * lcname, _zend_ast_list * args, _zend_function * fbc, unsigned int type) Line 3662	C
 	php7ts_debug.dll!zend_compile_call(_znode * result, _zend_ast * ast, unsigned int type) Line 3763	C
 	php7ts_debug.dll!zend_compile_var(_znode * result, _zend_ast * ast, unsigned int type) Line 8022	C
 	php7ts_debug.dll!zend_compile_expr(_znode * result, _zend_ast * ast) Line 7902	C
 	php7ts_debug.dll!zend_compile_stmt(_zend_ast * ast) Line 7871	C
 	php7ts_debug.dll!zend_compile_top_stmt(_zend_ast * ast) Line 7758	C
 	php7ts_debug.dll!zend_compile_top_stmt(_zend_ast * ast) Line 7752	C
 	php7ts_debug.dll!zend_compile(int type) Line 602	C
 	php7ts_debug.dll!compile_file(_zend_file_handle * file_handle, int type) Line 635	C
 	php7ts_debug.dll!zend_execute_scripts(int type, _zval_struct * retval, int file_count, ...) Line 1468	C
 	php7ts_debug.dll!php_execute_script(_zend_file_handle * primary_file) Line 2537	C
 	php.exe!do_cli(int argc, char * * argv) Line 994	C
 	php.exe!main(int argc, char * * argv) Line 1381	C
 	[External Code]	

I have not been able to reproduce the issue with current master.
 [2017-01-08 17:38 UTC] ab@php.net
@kshah, I really doubt it is a security issue. Unpredictable behavior - yes, as from Christoph's BT it lands at the unreachable code path. Your dump also shows 0xe8cb8bd6 as possibly being wrong. So it looks more like a first best exception that that was thrown. Also, given a specific PHP code is required to be written, which doesn't depend on any data, it sounds more like a not a security issue.

Thanks.
 [2017-01-08 19:19 UTC] ab@php.net
-Summary: Crash when calling undefined function from assert() on Windows +Summary: Crash when exporting **= in expansion of assign op -Status: Open +Status: Closed -Type: Security +Type: Bug -Assigned To: +Assigned To: ab
 [2017-01-08 19:19 UTC] ab@php.net
Got it. I've applied 9c3865eb6a7 which fixes the issue, was only applied to master previously. With debug symbols btw - you find them for every release or even snapshot build as a separate package on widows.php.net. Set to bug, lets keep closed till release, as there's a concern.

Thanks.
 [2017-01-08 19:32 UTC] nikic@php.net
Sorry, I marked this as non-private prior to reading the last comment. However, it looks like non-sec bugs are sent to the bugs list whether or not they're marked as private, so it doesn't really make a difference. Should that be changed? In any case, this is clearly not a security issue, because there is no remote exploitation vector.
 [2017-01-08 20:09 UTC] ab@php.net
Oh, i didn't check that :) Was tempted to do so myself as well also, because the patch was already public for many months.

But posting private bug mails to the public lists IMO is a bug, not what one would expect from "private".

thanks.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC