Bug #71535 [Asn->Csd]: Integer overflow in zend_mm_alloc_heap()
| From: | dmitry@php.net | Date: | Wed, 24 Feb 2016 08:06:15 +0000 |
| Subject: | Bug #71535 [Asn->Csd]: Integer overflow in zend_mm_alloc_heap() | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-199441@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=71535&edit=1
ID: 71535
Updated by: dmitry@php.net
Reported by: hlt99 at blinkenshell dot org
Summary: Integer overflow in zend_mm_alloc_heap()
-Status: Assigned
+Status: Closed
Type: Bug
Package: *General Issues
Operating System: Arch Linux (64-bit)
PHP Version: 7.0.3
Assigned To: dmitry
Block user comment: N
Private report: N
New Comment:
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=0b9c87a02bacfbf1d1383ad393bda78e5d65570c
Log: Fixed bug #71535 (Integer overflow in zend_mm_alloc_heap())
Previous Comments:
------------------------------------------------------------------------
[2016-02-17 17:11:35] hlt99 at blinkenshell dot org
The bug itself is located in Zend internal memory management code. It opens the door for memory
corruption vulns because PHP memory checks can be circumvented. I tried to demo this by chaining
this together with the other bug I reported.
However, this works only in debug mode. So I guess this is a low risk bug.
But be aware that this bug may as well be triggered by other bugs we don't know of.
------------------------------------------------------------------------
[2016-02-15 08:22:06] stas@php.net
You seem to be talking about debug mode build and also about internal function, so I'm not sure
I understand how it is a security issue. Could you please explain in some more details where the
security issue comes from?
------------------------------------------------------------------------
[2016-02-05 11:13:39] hlt99 at blinkenshell dot org
Description:
------------
# Build instructions
../configure --enable-debug --enable-exif && make
# Description
The debug code in zend_mm_alloc_heap() contains an integer overflow bug. As shown in the code
snippet below the code for memory alignment may increase the size parameter resulting in an integer
overflow.
(PHP-7.0.2) zend_alloc.c:
1346 static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t size
/*...*/)
1347 {
[...]
1349 #if ZEND_DEBUG
[...]
1355 size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
// ^-- possible int overflow
Overflowing the size parameter leads to a successful heap memory allocation.
Then a valid pointer pointing to a much smaller then requested heap memory
section is returned to the caller.
This bug can be triggered and exploited using [1].
[1] For more info on the security impact of that bug see #71534 (Type confusion
in exif_read_data() leading to heap overflow)!
# PHP versions known to be affected
7.0.2 (git)
7.0.3 (git)
Versions prior to 7.0.2 have not been tested.
# PHP versions known to be not affected
5.6.18 (git)
Versions prior to 5.6.18 have not been tested.
Test script:
---------------
/*
exif_read_data.php
poc.tiff:
http://hlt99.blinkenshell.org/php/poc.tiff
*/
<?php
$data = exif_read_data("poc.tiff", NULL, true, true);
?>
Expected result:
----------------
Fatal out of memory error
Actual result:
--------------
# GDB Log
$ gdb sapi/cli/php
[...]
gdb$ b exif.c:3675
gdb$ r exif_read_data.php
[...]
gdb$ si // until _safe_emalloc
[----------------------------------registers-----------------------------------]
RAX: 0xfc89
RBX: 0x1655c20 --> 0x607e ('~`')
RCX: 0xfa73fe ("/home/rc0r/tmp/php-src/ext/exif/exif.c")
RDX: 0x0
RSI: 0x1
RDI: 0xffffffffffffffff
RBP: 0x7fffffffaa00 --> 0x7ffff2e5ea00 --> 0x16199b8 --> 0xc89d20
(<php_stdiop_write>: push r14)
RSP: 0x7fffffffa730 --> 0x0
RIP: 0x878410 (<exif_process_IFD_in_TIFF+4560>: call 0xcd2480 <_safe_emalloc>)
R8 : 0xe5b
R9 : 0x0
R10: 0x1627348 --> 0x1645c20 --> 0x9200000000
R11: 0x7fffffffaa00 --> 0x7ffff2e5ea00 --> 0x16199b8 --> 0xc89d20
(<php_stdiop_write>: push r14)
R12: 0x1
R13: 0xe
R14: 0x1655c20 --> 0x607e ('~`')
R15: 0x1627348 --> 0x1645c20 --> 0x9200000000
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x878403 <exif_process_IFD_in_TIFF+4547>: lea rcx,[rip+0x72eff4] # 0xfa73fe
0x87840a <exif_process_IFD_in_TIFF+4554>: mov r15,r10
0x87840d <exif_process_IFD_in_TIFF+4557>: mov rbp,r11
=> 0x878410 <exif_process_IFD_in_TIFF+4560>: call 0xcd2480 <_safe_emalloc>
0x878415 <exif_process_IFD_in_TIFF+4565>: mov QWORD PTR [rbp+0x110],rax
0x87841c <exif_process_IFD_in_TIFF+4572>: mov rdi,QWORD PTR [rbp+0x0]
0x878420 <exif_process_IFD_in_TIFF+4576>: mov rsi,QWORD PTR [rbp+0x108]
0x878427 <exif_process_IFD_in_TIFF+4583>: xor edx,edx
Guessed arguments:
arg[0]: 0xffffffffffffffff
arg[1]: 0x1
arg[2]: 0x0
arg[3]: 0xfa73fe ("/home/rc0r/tmp/php-src/ext/exif/exif.c")
arg[4]: 0xe5b
arg[5]: 0x0
[------------------------------------------------------------------------------]
gdb$ si // until zend_mm_heap_alloc()
[----------------------------------registers-----------------------------------]
RAX: 0xffffffffffffffff
RBX: 0x1655c20 --> 0x4d2a ('*M')
RCX: 0xe5b
RDX: 0xfa73fe ("/home/rc0r/tmp/php-src/ext/exif/exif.c")
RSI: 0xffffffffffffffff
RDI: 0x7ffff2e00040 --> 0x0
RBP: 0x7fffffffaa00 --> 0x7ffff2e5ea00 --> 0x16199b8 --> 0xc89d20
(<php_stdiop_write>: push r14)
RSP: 0x7fffffffa700 --> 0x0
RIP: 0xcd2536 (<_safe_emalloc+182>: call 0xccefe0 <zend_mm_alloc_heap>)
R8 : 0x12fca48 ("/home/rc0r/tmp/php-src/Zend/zend_alloc.c")
R9 : 0x9ce
R10: 0xe5b
R11: 0x7ffff2e00040 --> 0x0
R12: 0x1
R13: 0xe
R14: 0x1627348 --> 0x1645c20 --> 0x9200000000
R15: 0x1627348 --> 0x1645c20 --> 0x9200000000
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xcd252d <_safe_emalloc+173>: mov rsi,rax
0xcd2530 <_safe_emalloc+176>: mov rdx,rcx
0xcd2533 <_safe_emalloc+179>: mov ecx,r10d
=> 0xcd2536 <_safe_emalloc+182>: call 0xccefe0 <zend_mm_alloc_heap>
0xcd253b <_safe_emalloc+187>: movzx ecx,WORD PTR [rbx]
0xcd253e <_safe_emalloc+190>: mov rdx,QWORD PTR [r14]
0xcd2541 <_safe_emalloc+193>: xor rcx,0x7ddb
0xcd2548 <_safe_emalloc+200>: inc BYTE PTR [rdx+rcx*1]
Guessed arguments:
arg[0]: 0x7ffff2e00040 --> 0x0
arg[1]: 0xffffffffffffffff
arg[2]: 0xfa73fe ("/home/rc0r/tmp/php-src/ext/exif/exif.c")
arg[3]: 0xe5b
arg[4]: 0x12fca48 ("/home/rc0r/tmp/php-src/Zend/zend_alloc.c")
arg[5]: 0x9ce
[------------------------------------------------------------------------------]
gdb$ si // until overflowing code is reached
[----------------------------------registers-----------------------------------]
RAX: 0x5fe9
RBX: 0x1655c20 --> 0x961 ('a\t')
RCX: 0xe5b
RDX: 0xfa73fe ("/home/rc0r/tmp/php-src/ext/exif/exif.c")
RSI: 0xffffffffffffffff
RDI: 0x7ffff2e00040 --> 0x0
RBP: 0xe5b
RSP: 0x7fffffffa670 --> 0x400007575
RIP: 0xccf040 (<zend_mm_alloc_heap+96>: add r15,0x27)
R8 : 0x12fca48 ("/home/rc0r/tmp/php-src/Zend/zend_alloc.c")
R9 : 0x9ce
R10: 0x1627348 --> 0x1645c20 --> 0x9200000000
R11: 0x7ffff2e00040 --> 0x0
R12: 0x7ffff2e00040 --> 0x0
R13: 0x1655c20 --> 0x961 ('a\t')
R14: 0x1627348 --> 0x1645c20 --> 0x9200000000
R15: 0xffffffffffffffff <-- size param
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xccf032 <zend_mm_alloc_heap+82>: cmp rsi,0x1
0xccf036 <zend_mm_alloc_heap+86>: mov r15d,0x1
0xccf03c <zend_mm_alloc_heap+92>: cmova r15,rsi
=> 0xccf040 <zend_mm_alloc_heap+96>: add r15,0x27 <-- overflow !!!
0xccf044 <zend_mm_alloc_heap+100>: and r15,0xfffffffffffffff8
0xccf048 <zend_mm_alloc_heap+104>: cmp r15,0xc00
0xccf04f <zend_mm_alloc_heap+111>: ja 0xccf0a5 <zend_mm_alloc_heap+197>
0xccf051 <zend_mm_alloc_heap+113>: movzx eax,WORD PTR [r13+0x0]
[------------------------------------------------------------------------------]
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=71535&edit=1