php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #73295 Invalid memory access in php_basename function
Submitted: 2016-10-11 16:48 UTC Modified: 2016-11-14 11:37 UTC
From: nguyenluan dot vnn at gmail dot com Assigned: stas (profile)
Status: Closed Package: Strings related
PHP Version: 7.0.11 OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: nguyenluan dot vnn at gmail dot com
New email:
PHP Version: OS:

 

 [2016-10-11 16:48 UTC] nguyenluan dot vnn at gmail dot com
Description:
------------
In function php_basename:

PHPAPI zend_string *php_basename(const char *s, size_t len, char *suffix, size_t sufflen)
{
	char *c, *comp, *cend;
	size_t inc_len, cnt;
	int state;
	zend_string *ret;

	c = comp = cend = (char*)s;
	cnt = len;  // (1) assign cnt as the flen from SPL_METHOD(SplFileInfo, getExtension)
	state = 0;
	while (cnt > 0) {  (2) cnt has very big value
		inc_len = (*c == '\0' ? 1 : php_mblen(c, cnt));  // crash here

		switch (inc_len) {

                ...
                ...

		c += inc_len;
		cnt -= inc_len;
	}

quit_loop:

...
...
}

The index for the while loop is cnt may have very big value (I guess due to sign extension), so when it reach out the length of input string an invalid memory access is happened and causes PHP 7 to crash.

Test script:
---------------
<?php
    ini_set('memory_limit', -1);
    $info = new SplFileInfo('foo.'.str_repeat('a', 0x80001000));

    var_dump(strlen($info->getExtension()));
?>

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

Actual result:
--------------
gdb-peda$ r ../test/string/test.php 
Starting program: /home/user/Desktop/php-7.0.11/sapi/cli/php ../test/string/test.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

 [----------------------------------registers-----------------------------------]
RAX: 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
RBX: 0x0 
RCX: 0x0 
RDX: 0x0 
RSI: 0xffffffff80001004 
RDI: 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
RBP: 0x7fffffffa6a0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
RSP: 0x7fffffffa640 --> 0x0 
RIP: 0x8c85fb (<php_basename+48>:	mov    rax,QWORD PTR [rbp-0x50])
R8 : 0x158d1c0 --> 0x7fffffffd901 --> 0xc0000000000164d1 
R9 : 0x7fffed279090 --> 0xc002000800000002 
R10: 0x4 
R11: 0x206 
R12: 0x445010 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe1a0 --> 0x2 
R14: 0x7fffed214030 --> 0x7fffed2821e0 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7fffed2821e0 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8c85ef <php_basename+36>:	mov    QWORD PTR [rbp-0x28],rax
   0x8c85f3 <php_basename+40>:	mov    rax,QWORD PTR [rbp-0x28]
   0x8c85f7 <php_basename+44>:	mov    QWORD PTR [rbp-0x30],rax
=> 0x8c85fb <php_basename+48>:	mov    rax,QWORD PTR [rbp-0x50]
   0x8c85ff <php_basename+52>:	mov    QWORD PTR [rbp-0x10],rax
   0x8c8603 <php_basename+56>:	mov    DWORD PTR [rbp-0x38],0x0
   0x8c860a <php_basename+63>:	jmp    0x8c86d4 <php_basename+265>
   0x8c860f <php_basename+68>:	mov    rax,QWORD PTR [rbp-0x30]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa640 --> 0x0 
0008| 0x7fffffffa648 --> 0x0 
0016| 0x7fffffffa650 --> 0xffffffff80001004 
0024| 0x7fffffffa658 --> 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
0032| 0x7fffffffa660 --> 0x158d700 --> 0x70600000001 
0040| 0x7fffffffa668 --> 0x158d200 --> 0x700000001 
0048| 0x7fffffffa670 --> 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
0056| 0x7fffffffa678 --> 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 3, php_basename (
    s=0x7fff6cc00000 "foo.", 'a' <repeats 196 times>..., 
    len=0xffffffff80001004, suffix=0x0, sufflen=0x0)
    at /home/user/Desktop/php-7.0.11/ext/standard/string.c:1560
1560		cnt = len;

gdb-peda$ p len
$25 = 0xffffffff80001004

gdb-peda$ n

 [----------------------------------registers-----------------------------------]
RAX: 0xffffffff80001004 
RBX: 0x0 
RCX: 0x0 
RDX: 0x0 
RSI: 0xffffffff80001004 
RDI: 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
RBP: 0x7fffffffa6a0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
RSP: 0x7fffffffa640 --> 0x0 
RIP: 0x8c8603 (<php_basename+56>:	mov    DWORD PTR [rbp-0x38],0x0)
R8 : 0x158d1c0 --> 0x7fffffffd901 --> 0xc0000000000164d1 
R9 : 0x7fffed279090 --> 0xc002000800000002 
R10: 0x4 
R11: 0x206 
R12: 0x445010 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe1a0 --> 0x2 
R14: 0x7fffed214030 --> 0x7fffed2821e0 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7fffed2821e0 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8c85f7 <php_basename+44>:	mov    QWORD PTR [rbp-0x30],rax
   0x8c85fb <php_basename+48>:	mov    rax,QWORD PTR [rbp-0x50]
   0x8c85ff <php_basename+52>:	mov    QWORD PTR [rbp-0x10],rax
=> 0x8c8603 <php_basename+56>:	mov    DWORD PTR [rbp-0x38],0x0
   0x8c860a <php_basename+63>:	jmp    0x8c86d4 <php_basename+265>
   0x8c860f <php_basename+68>:	mov    rax,QWORD PTR [rbp-0x30]
   0x8c8613 <php_basename+72>:	movzx  eax,BYTE PTR [rax]
   0x8c8616 <php_basename+75>:	test   al,al
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa640 --> 0x0 
0008| 0x7fffffffa648 --> 0x0 
0016| 0x7fffffffa650 --> 0xffffffff80001004 
0024| 0x7fffffffa658 --> 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
0032| 0x7fffffffa660 --> 0x158d700 --> 0x70600000001 
0040| 0x7fffffffa668 --> 0x158d200 --> 0x700000001 
0048| 0x7fffffffa670 --> 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
0056| 0x7fffffffa678 --> 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
1561		state = 0;

gdb-peda$ p cnt
$26 = 0xffffffff80001004

gdb-peda$ c
Continuing.

Program received signal SIGSEGV, Segmentation fault.

 [----------------------------------registers-----------------------------------]
RAX: 0x7fffecc02000 
RBX: 0x0 
RCX: 0x0 
RDX: 0xffffffff 
RSI: 0x1 
RDI: 0x7fffffffa5c0 --> 0x7fffffffa620 --> 0x7fffed214030 --> 0x7fffed2821e0 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
RBP: 0x7fffffffa6a0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
RSP: 0x7fffffffa640 --> 0x0 
RIP: 0x8c8613 (<php_basename+72>:	movzx  eax,BYTE PTR [rax])
R8 : 0x0 
R9 : 0x1 
R10: 0x7fffffffa5c8 --> 0x7fffecc01004 --> 0x0 
R11: 0x246 
R12: 0x445010 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe1a0 --> 0x2 
R14: 0x7fffed214030 --> 0x7fffed2821e0 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7fffed2821e0 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8c8603 <php_basename+56>:	mov    DWORD PTR [rbp-0x38],0x0
   0x8c860a <php_basename+63>:	jmp    0x8c86d4 <php_basename+265>
   0x8c860f <php_basename+68>:	mov    rax,QWORD PTR [rbp-0x30]
=> 0x8c8613 <php_basename+72>:	movzx  eax,BYTE PTR [rax]
   0x8c8616 <php_basename+75>:	test   al,al
   0x8c8618 <php_basename+77>:	je     0x8c8631 <php_basename+102>
   0x8c861a <php_basename+79>:	mov    rdx,QWORD PTR [rbp-0x10]
   0x8c861e <php_basename+83>:	mov    rax,QWORD PTR [rbp-0x30]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa640 --> 0x0 
0008| 0x7fffffffa648 --> 0x0 
0016| 0x7fffffffa650 --> 0xffffffff80001004 
0024| 0x7fffffffa658 --> 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
0032| 0x7fffffffa660 --> 0x158d700 --> 0x70600000001 
0040| 0x7fffffffa668 --> 0x1 
0048| 0x7fffffffa670 --> 0x7fffecc02000 
0056| 0x7fffffffa678 --> 0x7fff6cc00000 ("foo.", 'a' <repeats 196 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00000000008c8613 in php_basename (
    s=0x7fff6cc00000 "foo.", 'a' <repeats 196 times>..., 
    len=0xffffffff80001004, suffix=0x0, sufflen=0x0)
    at /home/user/Desktop/php-7.0.11/ext/standard/string.c:1563
1563			inc_len = (*c == '\0' ? 1 : php_mblen(c, cnt));

gdb-peda$ p c
$27 = 0x7fffecc02000 <error: Cannot access memory at address 0x7fffecc02000>

gdb-peda$ p cnt
$28 = 0xfffffffefffff004

gdb-peda$ p s
$29 = 0x7fff6cc00000 "foo.", 'a' <repeats 196 times>...

gdb-peda$ p c - s
$30 = 0x80002000

gdb-peda$ bt
#0  0x00000000008c8613 in php_basename (
    s=0x7fff6cc00000 "foo.", 'a' <repeats 196 times>..., 
    len=0xffffffff80001004, suffix=0x0, sufflen=0x0)
    at /home/user/Desktop/php-7.0.11/ext/standard/string.c:1563
#1  0x00000000008447f0 in zim_spl_SplFileInfo_getExtension (
    execute_data=0x7fffed2141a0, return_value=0x7fffed214100)
    at /home/user/Desktop/php-7.0.11/ext/spl/spl_directory.c:936
#2  0x0000000000ab00e1 in ZEND_DO_FCALL_SPEC_HANDLER ()
    at /home/user/Desktop/php-7.0.11/Zend/zend_vm_execute.h:842
#3  0x0000000000aaef61 in execute_ex (ex=0x7fffed214030)
    at /home/user/Desktop/php-7.0.11/Zend/zend_vm_execute.h:414
#4  0x0000000000aaf072 in zend_execute (op_array=0x7fffed281000, 
    return_value=0x0)
    at /home/user/Desktop/php-7.0.11/Zend/zend_vm_execute.h:458
#5  0x0000000000a5014b in zend_execute_scripts (type=0x8, retval=0x0, 
    file_count=0x3) at /home/user/Desktop/php-7.0.11/Zend/zend.c:1427
#6  0x00000000009b8557 in php_execute_script (primary_file=0x7fffffffce20)
    at /home/user/Desktop/php-7.0.11/main/main.c:2494
#7  0x0000000000b18327 in do_cli (argc=0x2, argv=0x146e560)
    at /home/user/Desktop/php-7.0.11/sapi/cli/php_cli.c:974
#8  0x0000000000b194f5 in main (argc=0x2, argv=0x146e560)
    at /home/user/Desktop/php-7.0.11/sapi/cli/php_cli.c:1344
#9  0x00007ffff416f830 in __libc_start_main (main=0xb18cea <main>, argc=0x2, 
    argv=0x7fffffffe1a8, init=<optimized out>, fini=<optimized out>, 
    rtld_fini=<optimized out>, stack_end=0x7fffffffe198)
    at ../csu/libc-start.c:291
#10 0x0000000000445039 in _start ()


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-11-05 21:50 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2016-11-05 21:50 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2016-11-11 13:09 UTC] nguyenluan dot vnn at gmail dot com
-Status: Closed +Status: Assigned
 [2016-11-11 13:09 UTC] nguyenluan dot vnn at gmail dot com
Still crashes in version 7.0.13. Please check again.
 [2016-11-11 13:09 UTC] nguyenluan dot vnn at gmail dot com
-Status: Assigned +Status: Open
 [2016-11-11 13:09 UTC] nguyenluan dot vnn at gmail dot com
Open again.
 [2016-11-13 16:11 UTC] ab@php.net
@nguyenluan dot vnn at gmail dot com, thanks for checking. As the previous comment stated, the fix has landed. Please check either the dev branch or the next planned RC.

Thanks.
 [2016-11-14 11:37 UTC] nguyenluan dot vnn at gmail dot com
-Status: Assigned +Status: Closed
 [2016-11-14 11:37 UTC] nguyenluan dot vnn at gmail dot com
I checked with PHP 7.1.0 RC6. This issue is fixed.

Please close. Thanks
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Thu Dec 12 06:01:24 2019 UTC