Menu

#69 global-buffer-overflow bug while parsing GIF file

v1.0 (example)
closed-fixed
None
7
2017-12-28
2017-10-17
No

From https://bugs.debian.org/878839


Running 'optipng' with the attached file raises global-buffer-overflow
bug,
which may allow a remote attacker to cause a denial-of-service attack or
other unspecified impact with a crafted file.

I expected the program to terminate without segfault, but the program
crashes as follow


  • Please consider that this bug isn't found in default debian optipng *
  • which is installed by apt-get. *
  • This bug is only triggered when optipng was compiled by clang or by *
  • gcc without any optimizations. *


<logs with="" address="" sanitizer="">

june@june:~/project/analyze/poc/optipng$ optipng poc
** Processing: poc
Warning: Bogus data in GIF
=================================================================
==11381==ERROR: AddressSanitizer: global-buffer-overflow on address
0x55c9084bf040 at pc 0x55c908286630 bp 0x7fffd3831e40 sp 0x7fffd3831e38
WRITE of size 4 at 0x55c9084bf040 thread T0
=================================================================
==11381==ERROR: AddressSanitizer: global-buffer-overflow on address
0x55c9084bf040 at pc 0x55c908286630 bp 0x7fffd3831e40 sp 0x7fffd3831e38
WRITE of size 4 at 0x55c9084bf040 thread T0
#0 0x55c90828662f
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x7362f)
#1 0x55c908285912
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x72912)
#2 0x55c90828549f
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x7249f)
#3 0x55c908284e00
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x71e00)
#4 0x55c908239928
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x26928)
#5 0x55c9082367a7
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x237a7)
#6 0x55c908229674
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x16674)
#7 0x55c90822b778
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x18778)
#8 0x55c90822c9fe
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x199fe)
#9 0x55c90822731e
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x1431e)
#10 0x55c908227436
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x14436)
#11 0x7fb1b02de2b0 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
#12 0x55c908224389
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x11389)
0x55c9084bf040 is located 0 bytes to the right of global variable
'stack' defined in 'gifread.c:401:16' (0x55c9084b7040) of size 32768
0x55c9084bf040 is located 32 bytes to the left of global variable
'oldcode' defined in 'gifread.c:398:27' (0x55c9084bf060) of size 4
SUMMARY: AddressSanitizer: global-buffer-overflow
(/home/june/project/analyze/bins/optipng-0.7.6/src/optipng/optipng+0x7362f)
Shadow bytes around the buggy address:
  0x0ab9a108fdb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ab9a108fdc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ab9a108fdd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ab9a108fde0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ab9a108fdf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ab9a108fe00: 00 00 00 00 00 00 00 00[f9]f9 f9 f9 04 f9 f9 f9
  0x0ab9a108fe10: f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x0ab9a108fe20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ab9a108fe30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ab9a108fe40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ab9a108fe50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable:           00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone:       fa
Heap right redzone:      fb
Freed heap region:       fd
Stack left redzone:      f1
Stack mid redzone:       f2
Stack right redzone:     f3
Stack partial redzone:   f4
Stack after return:      f5
Stack use after scope:   f8
Global redzone:          f9
Global init order:       f6
Poisoned by user:        f7
Container overflow:      fc
Array cookie:            ac
Intra object redzone:    bb
ASan internal:           fe
Left alloca redzone:     ca
Right alloca redzone:    cb
==11381==ABORTING

<stack trace>
(gdb) r poc
Starting program: /usr/bin/optipng poc
** Processing: poc
Warning: Bogus data in GIF

Program received signal SIGSEGV, Segmentation fault.
0x000055555557d075 in LZWReadByte (init_flag=0, input_code_size=2,
stream=0x55555579e010)
    at gifread.c:499
    499             *sp++ = table[1][code];
(gdb) bt
#0  0x000055555557d075 in LZWReadByte (init_flag=0, input_code_size=2,
stream=0x55555579e010) at gifread.c:499
#1  0x000055555557ca05 in GIFReadImageData (image=0x7fffffffb310,
stream=0x55555579e010) at gifread.c:261
#2  0x000055555557c846 in GIFReadNextImage (image=0x7fffffffb310,
stream=0x55555579e010) at gifread.c:217
#3  0x000055555557c618 in GIFReadNextBlock (image=0x7fffffffb310,
ext=0x7fffffffb2f0, stream=0x55555579e010) at gifread.c:163
#4  0x0000555555561055 in pngx_read_gif (png_ptr=0x55555579e240,
info_ptr=0x55555579e4a0, stream=0x55555579e010) at pngxrgif.c:151
#5  0x000055555555f658 in pngx_read_image (png_ptr=0x55555579e240,
info_ptr=0x55555579e4a0, fmt_name_ptr=0x7fffffffbc30,
fmt_long_name_ptr=0x0) at pngxread.c:130
#6  0x0000555555558d3b in opng_read_file (infile=0x55555579e010) at
optim.c:939
#7  0x000055555555a106 in opng_optimize_impl (infile_name=0x7fffffffe487
"poc") at optim.c:1503
#8  0x000055555555b01b in opng_optimize (infile_name=0x7fffffffe487
"poc") at optim.c:1853
#9  0x0000555555557525 in process_files (argc=2, argv=0x7fffffffe178) at
optipng.c:941
#10 0x00005555555575da in main (argc=2, argv=0x7fffffffe178) at
optipng.c:975

This bug happened because below loop worked infinitely.

while (code >= clear_code)
{
  *sp++ = table[1][code];
  if (code == table[0][code])
    GIFError("GIF/LZW error: circular table entry");
  code = table[0][code];
}
(gdb) p table[0]
$3 = {0, 0, 0, 0, 0, 0, 3, 0, 0, 15, 9, 15, 8, 10, 1, 13, 0 <repeats
4080 times>}

code value is assigned 15 -> 13 -> 10 -> 9 -> 15 -> 13 -> 10 -> 9 -> ...
repetedely.
15, 13, 10, 9 are always bigger than clear_code so this loop runs
forever
and sp pointer will increase forever which causes buffer overflow.


The bug was found with a fuzzer developed by 'SoftSec' group at KAIST.


1 Attachments

Discussion

  • Cosmin Truta

    Cosmin Truta - 2017-10-23

    Confirmed. Marking this defect as high severity.
    Thank you very much for the report.

     
  • Cosmin Truta

    Cosmin Truta - 2017-10-23
    • assigned_to: Cosmin Truta
    • Priority: 5 --> 7
     
  • Cosmin Truta

    Cosmin Truta - 2017-11-27

    I am attaching an interim fix. See optipng-076-sfbug-69.patch

    I have a bunch of changes and fixes (including this one) piled up, so new release is due. I cannot publish that release just yet, but I am targetting it for some time before the end of this year.

     
  • Sebastian Pipping

    This issue got assigned CVE number CVE-2017-16938 in the meantime, so for reference: https://nvd.nist.gov/vuln/detail/CVE-2017-16938

     
  • Cosmin Truta

    Cosmin Truta - 2017-12-28
    • status: open --> closed-fixed
     
  • Cosmin Truta

    Cosmin Truta - 2017-12-28

    Fixed in OptiPNG version 0.7.7. Thanks again for the report.

     

Log in to post a comment.