SecurityTracker.com
Keep Track of the Latest Vulnerabilities
with SecurityTracker!
    Home    |    View Topics    |    Search    |    Contact Us    |   

SecurityTracker
Archives


Try our Premium Alert Service
 
Sign Up
Sign Up for Your FREE Weekly SecurityTracker E-mail Alert Summary
Instant Alerts
Buy our Premium Vulnerability Notification Service to receive customized, instant alerts
Affiliates
Put SecurityTracker Vulnerability Alerts on Your Web Site -- It's Free!
Partners
Become a Partner and License Our Database or Notification Service





Category:   Application (Generic)  >   GD Library Vendors:   Boutell.com
GD Library Heap Overflow in Processing Files Lets Remote Users Execute Arbitrary Code
SecurityTracker Alert ID:  1035659
SecurityTracker URL:  http://securitytracker.com/id/1035659
CVE Reference:   CVE-2016-3074   (Links to External Site)
Date:  Apr 22 2016
Impact:   Execution of arbitrary code via network, User access via network
Fix Available:  Yes  Vendor Confirmed:  Yes  Exploit Included:  Yes  
Version(s): 2.1.1
Description:   A vulnerability was reported in GD Library (libgd). A remote user can cause arbitrary code to be executed on the target system.

A remote user can create a file containing specially crafted compressed gd2 data that, when loaded by the target application, will trigger a signedness error and resulting heap overflow to execute arbitrary code on the target system. The code will run with the privileges of the target application.

Hans Jerry Illikainen reported this vulnerability.

Impact:   A remote user can create content that, when loaded by the target user, will execute arbitrary code on the target system.
Solution:   The vendor has issued a source code fix, available at:

https://github.com/libgd/libgd/commit/2bb97f407c1145c850416a3bfbcc8cf124e68a19

Vendor URL:  libgd.github.io/ (Links to External Site)
Cause:   Boundary error

Message History:   This archive entry has one or more follow-up message(s) listed below.
Aug 20 2016 (HP Issues Fix for HPE NonStop Server) GD Library Heap Overflow in Processing Files Lets Remote Users Execute Arbitrary Code
HP has issued a fix for HPE NonStop Server.
Jul 13 2017 (Juniper Issues Fix for Juniper Junos) GD Library Heap Overflow in Processing Files Lets Remote Users Execute Arbitrary Code
Juniper has issued a fix for Juniper Junos.



 Source Message Contents

Subject:  CVE-2016-3074: libgd: signedness vulnerability

Overview
========

libgd [1] is an open-source image library.  It is perhaps primarily used
by the PHP project.  It has been bundled with the default installation
of PHP since version 4.3 [2].

A signedness vulnerability (CVE-2016-3074) exist in libgd 2.1.1 which
may result in a heap overflow when processing compressed gd2 data.


Details
=======

4 bytes representing the chunk index size is stored in a signed integer,
chunkIdx[i].size, by `gdGetInt()' during the parsing of GD2 headers:

libgd-2.1.1/src/gd_gd2.c:
,----
|  53 typedef struct {
|  54     int offset;
|  55     int size;
|  56 }
|  57 t_chunk_info;
`----

libgd-2.1.1/src/gd_gd2.c:
,----
|  65 static int
|  66 _gd2GetHeader (gdIOCtxPtr in, int *sx, int *sy,
|  67                int *cs, int *vers, int *fmt, int *ncx, int *ncy,
|  68                t_chunk_info ** chunkIdx)
|  69 {
| ...
|  73     t_chunk_info *cidx;
| ...
| 155     if (gd2_compressed (*fmt)) {
| ...
| 163         for (i = 0; i < nc; i++) {
| ...
| 167             if (gdGetInt (&cidx[i].size, in) != 1) {
| 168                 goto fail2;
| 169             };
| 170         };
| 171         *chunkIdx = cidx;
| 172     };
| ...
| 181 }
`----

`gdImageCreateFromGd2Ctx()' and `gdImageCreateFromGd2PartCtx()' then
allocates memory for the compressed data based on the value of the
largest chunk size:

libgd-2.1.1/src/gd_gd2.c:
,----
| 371|637     if (gd2_compressed (fmt)) {
| 372|638         /* Find the maximum compressed chunk size. */
| 373|639         compMax = 0;
| 374|640         for (i = 0; (i < nc); i++) {
| 375|641             if (chunkIdx[i].size > compMax) {
| 376|642                 compMax = chunkIdx[i].size;
| 377|643             };
| 378|644         };
| 379|645         compMax++;
| ...|...
| 387|656         compBuf = gdCalloc (compMax, 1);
| ...|...
| 393|661     };
`----

A size of <= 0 results in `compMax' retaining its initial value during
the loop, followed by it being incremented to 1.  Since `compMax' is
used as the nmemb for `gdCalloc()', this leads to a 1*1 byte allocation
for `compBuf'.

This is followed by compressed data being read to `compBuf' based on the
current (potentially negative) chunk size:

libgd-2.1.1/src/gd_gd2.c:
,----
| 339 BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Ctx (gdIOCtxPtr in)
| 340 {
| ...
| 413         if (gd2_compressed (fmt)) {
| 414
| 415             chunkLen = chunkMax;
| 416
| 417             if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
| 418                                 compBuf,
| 419                                 chunkIdx[chunkNum].size,
| 420                                 (char *) chunkBuf, &chunkLen, in)) {
| 421                 GD2_DBG (printf ("Error reading comproessed chunk\n"));
| 422                 goto fail;
| 423             };
| 424
| 425             chunkPos = 0;
| 426         };
| ...
| 501 }
`----


libgd-2.1.1/src/gd_gd2.c:
,----
| 585 BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
| 586 {
| ...
| 713         if (!gd2_compressed (fmt)) {
| ...
| 731         } else {
| 732             chunkNum = cx + cy * ncx;
| 733
| 734             chunkLen = chunkMax;
| 735             if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
| 736                                 compBuf,
| 737                                 chunkIdx[chunkNum].size,
| 738                                 (char *) chunkBuf, &chunkLen, in)) {
| 739                 printf ("Error reading comproessed chunk\n");
| 740                 goto fail2;
| 741             };
| ...
| 746         };
| ...
| 815 }
`----

The size is subsequently interpreted as a size_t by `fread()' or
`memcpy()', depending on how the image is read:

libgd-2.1.1/src/gd_gd2.c:
,----
| 221 static int
| 222 _gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf,
| 223            uLongf * chunkLen, gdIOCtx * in)
| 224 {
| ...
| 236     if (gdGetBuf (compBuf, compSize, in) != compSize) {
| 237         return FALSE;
| 238     };
| ...
| 251 }
`----

libgd-2.1.1/src/gd_io.c:
,----
| 211 int gdGetBuf(void *buf, int size, gdIOCtx *ctx)
| 212 {
| 213     return (ctx->getBuf)(ctx, buf, size);
| 214 }
`----


For file contexts:

libgd-2.1.1/src/gd_io_file.c:
,----
|  52 BGD_DECLARE(gdIOCtx *) gdNewFileCtx(FILE *f)
|  53 {
| ...
|  67     ctx->ctx.getBuf = fileGetbuf;
| ...
|  76 }
| ...
|  92 static int fileGetbuf(gdIOCtx *ctx, void *buf, int size)
|  93 {
|  94     fileIOCtx *fctx;
|  95     fctx = (fileIOCtx *)ctx;
|  96
|  97     return (fread(buf, 1, size, fctx->f));
|  98 }
`----


And for dynamic contexts:

libgd-2.1.1/src/gd_io_dp.c:
,----
|  74 BGD_DECLARE(gdIOCtx *) gdNewDynamicCtxEx(int initialSize, void *data, int freeOKFlag)
|  75 {
| ...
|  95     ctx->ctx.getBuf = dynamicGetbuf;
| ...
| 104 }
| ...
| 256 static int dynamicGetbuf(gdIOCtxPtr ctx, void *buf, int len)
| 257 {
| ...
| 280     memcpy(buf, (void *) ((char *)dp->data + dp->pos), rlen);
| ...
| 284 }
`----


PoC
===

Against Ubuntu 15.10 amd64 running nginx with php5-fpm and php5-gd [3]:

,----
| $ python exploit.py --bind-port 5555 http://1.2.3.4/upload.php
| [*] this may take a while
| [*] offset 912 of 10000...
| [+] connected to 1.2.3.4:5555
| id
| uid=33(www-data) gid=33(www-data) groups=33(www-data)
| 
| uname -a
| Linux wily64 4.2.0-35-generic #40-Ubuntu SMP Tue Mar 15 22:15:45 UTC
| 2016 x86_64 x86_64 x86_64 GNU/Linux
| 
| dpkg -l|grep -E "php5-(fpm|gd)"
| ii  php5-fpm       5.6.11+dfsg-1ubuntu3.1 ...
| ii  php5-gd        5.6.11+dfsg-1ubuntu3.1 ...
| 
| cat upload.php
| <?php
|     imagecreatefromgd2($_FILES["file"]["tmp_name"]);
| ?>
`----


Solution
========

This bug has been fixed in git HEAD [4].



Footnotes
_________

[1] [http://libgd.org/]

[2] [https://en.wikipedia.org/wiki/Libgd]

[3] [https://github.com/dyntopia/exploits/tree/master/CVE-2016-3074]

[4] [https://github.com/libgd/libgd/commit/2bb97f407c1145c850416a3bfbcc8cf124e68a19]


-- 
Hans Jerry Illikainen
 
 


Go to the Top of This SecurityTracker Archive Page





Home   |    View Topics   |    Search   |    Contact Us

This web site uses cookies for web analytics. Learn More

Copyright 2018, SecurityGlobal.net LLC