Potential infinite loop in gdImageCreateFromGifCtx

Sec Bug #75571 Potential infinite loop in gdImageCreateFromGifCtx
Submitted: 2017-11-25 16:53 UTC Modified: 2018-01-16 09:05 UTC
From: orange at chroot dot org Assigned: stas (profile)
Status: Closed Package: GD related
PHP Version: 5.6.32 OS: Ubuntu 17.10
Private report: No CVE-ID: 2018-5711

 [2017-11-25 16:53 UTC] orange at chroot dot org

Description:
------------
Hi, I found an infinity loop in GD GIF core parsing function. 

It is easy to trigger in web application if the web use GD as its image library. For example, It can be triggered by the following functions

* imagecreatefromgif
* imagecreatefromstring

This vulnerability will lead to a Denied of Service and exhausted the server resource.



There is a do-while in file `ext/gd/libgd/gd_gif_in.c` and function `LWZReadByte_`
```
do {
    sd->firstcode = sd->oldcode =
    GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP);
} while (sd->firstcode == sd->clear_code);
```
https://github.com/php/php-src/blob/c5767db441e4db2a1e07b5880129ad7ce0b25b6f/ext/gd/libgd/gd_gif_in.c#L460


The implementation of `GetCode` is in `GetCode_`
```
static int
GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP)
{
    int           i, j, ret;
    unsigned char count;

    ... 

    if ((count = GetDataBlock(fd, &scd->buf[2], ZeroDataBlockP)) <= 0)
        scd->done = TRUE;

    ...
}
```
https://github.com/php/php-src/blob/c5767db441e4db2a1e07b5880129ad7ce0b25b6f/ext/gd/libgd/gd_gif_in.c#L376

As you can see, `GetDataBlock` will read the image data and return the length. If EOF, returned -1. But the variable `count` is `unsigned char`, will always be positive value. So the line `scd->done = TRUE` will never be executed.


I think the easiest patch is change `unsigned char` to `int`.



Test script:
---------------
$ curl https://gist.githubusercontent.com/orangetw/adb0e2519df267eb54d8b68027a91d4c/raw/7a7d6938f59dd89e9a9b7304d71f8f6640609479/poc.gif.xxd | xxd -r > poc.gif

$ php -r 'imagecreatefromgif("poc.gif");'
hang here...



Patches

fix-75571 (last revision 2017-11-29 18:54 UTC by cmb@php.net)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports

 [2017-11-28 17:19 UTC] cmb@php.net

-Assigned To: +Assigned To: cmb

 [2017-11-29 18:53 UTC] cmb@php.net

-Summary: Infinity loop in GD GIF parsing function leads to Denied of Service +Summary: Potential infinite loop in gdImageCreateFromGifCtx -Status: Assigned +Status: Analyzed -Assigned To: cmb +Assigned To: stas

 [2017-11-29 18:53 UTC] cmb@php.net

Thanks for reporting this issue!  Indeed, this is an exploitable
Denial of Service vulnerability, and all PHP versions are
affected.  Furthermore, libgd is also affected; I have already
forwarded this issue to security@libgd.org including a respective
patch.

Stas, can you please commit the patch I'm going to attach to the
security repo (PHP-5.6 and up)?  It would be nice if it were
possible to sync the respective releases of GD and PHP.

 [2018-01-02 04:27 UTC] stas@php.net

-PHP Version: 7.2Git-2017-11-25 (Git) +PHP Version: 5.6.32

 [2018-01-02 04:27 UTC] stas@php.net

-Status: Analyzed +Status: Closed

 [2018-01-16 09:05 UTC] kaplan@php.net

-CVE-ID: needed +CVE-ID: 2018-5711