LibTIFF pal2rgb 4.0.9 - Heap Buffer Overflow

EDB-ID:

43322


Type:

dos


Platform:

Linux

Date:

2017-12-11


Source: http://bugzilla.maptools.org/show_bug.cgi?id=2750

The vulnerability is triggered by ./tools/pal2rgb $FILE /dev/null

The asan debug information is below:

TIFFFetchNormalTag: Warning, IO error during reading of "XResolution"; tag
ignored.
TIFFFetchNormalTag: Warning, IO error during reading of "YResolution"; tag
ignored.
sample.tiff: JPEG compression support is not configured.
TIFFSetField: /dev/null: Unknown pseudo-tag 65537.
TIFFSetField: /dev/null: Unknown pseudo-tag 65538.
sample.tiff: JPEG compression support is not configured.
=================================================================
==29649==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x611000009fe1 at pc 0x0000004f3109 bp 0x7fff697434d0 sp 0x7fff697434c8
WRITE of size 1 at 0x611000009fe1 thread T0
    #0 0x4f3108  (/home/vagrant/targets/asan/tt/tools/pal2rgb+0x4f3108)
    #1 0x7f678dc0cf44  (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #2 0x419ba5  (/home/vagrant/targets/asan/tt/tools/pal2rgb+0x419ba5)

0x611000009fe1 is located 0 bytes to the right of 225-byte region
[0x611000009f00,0x611000009fe1)
allocated by thread T0 here:
    #0 0x4c3f08  (/home/vagrant/targets/asan/tt/tools/pal2rgb+0x4c3f08)
    #1 0x4f2748  (/home/vagrant/targets/asan/tt/tools/pal2rgb+0x4f2748)
    #2 0x7f678dc0cf44  (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)

SUMMARY: AddressSanitizer: heap-buffer-overflow
(/home/vagrant/targets/asan/tt/tools/pal2rgb+0x4f3108)
Shadow bytes around the buggy address:
  0x0c227fff93a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c227fff93f0: 00 00 00 00 00 00 00 00 00 00 00 00[01]fa fa fa
  0x0c227fff9400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9410: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9420: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9430: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9440: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==29649==ABORTING

pal2rgb allocates the output buffer(obuf) too small at tools/pal2rgb.c:188.
That cause heap overflow and lead to memory corruption in TIFFSetupStrips().

(gdb) r sample.tiff /dev/null
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/vagrant/targets/asan/tt/tools/pal2rgb sample.tiff
/dev/null
TIFFFetchNormalTag: Warning, IO error during reading of "XResolution"; tag
ignored.
TIFFFetchNormalTag: Warning, IO error during reading of "YResolution"; tag
ignored.
sample.tiff: JPEG compression support is not configured.
TIFFSetField: /dev/null: Unknown pseudo-tag 65537.
TIFFSetField: /dev/null: Unknown pseudo-tag 65538.
sample.tiff: JPEG compression support is not configured.
*** Error in `/home/vagrant/targets/asan/tt/tools/pal2rgb': malloc(): memory
corruption: 0x0000000000652160 ***

Program received signal SIGABRT, Aborted.
0x00007ffff7741c37 in __GI_raise (sig=sig@entry=6) at
../nptl/sysdeps/unix/sysv/linux/raise.c:56
56    ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff7741c37 in __GI_raise (sig=sig@entry=6) at
../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff7745028 in __GI_abort () at abort.c:89
#2  0x00007ffff777e2a4 in __libc_message (do_abort=1,
    fmt=fmt@entry=0x7ffff7890310 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007ffff778c584 in malloc_printerr (ptr=0x652160,
    str=0x7ffff788c4df "malloc(): memory corruption", action=<optimized out>)
at malloc.c:4998
#4  _int_malloc (av=0x7ffff7acd760 <main_arena>, bytes=24) at malloc.c:3449
#5  0x00007ffff778dae0 in __GI___libc_malloc (bytes=24) at malloc.c:2893
#6  0x00000000004122a5 in TIFFSetupStrips (tif=tif@entry=0x651b80) at
tif_write.c:545
#7  0x00000000004124b5 in TIFFWriteCheck (tif=0x651b80, tiles=<optimized out>,
    module=0x42de50 <module> "TIFFWriteScanline") at tif_write.c:613
#8  0x0000000000412a74 in TIFFWriteScanline (tif=tif@entry=0x651b80,
buf=buf@entry=0x652070,
    row=row@entry=0, sample=sample@entry=0) at tif_write.c:56
#9  0x0000000000401dbd in main (argc=<optimized out>, argv=<optimized out>) at
pal2rgb.c:200

Affected version: 4.0.9
Latest version: 4.0.9

pal2rgb allocate output buffer to convert TIFF format. The output buffer always
uses a fixed size(225).  However, when write data to output buffer, imagewidth
and imagelength of the input TIFF file are used. it lead to heap overflow.

1) get imagewidth and imagelength from input TIFF

tools/pal2rgb.c:142     TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imagewidth);
tools/pal2rgb.c:143     TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);

2) allocate output buffer
tools/pal2rgb.c:188       obuf = (unsigned
char*)_TIFFmalloc(TIFFScanlineSize(out)); // TIFFScanlineSize(out) returns
always 225.

3) write data to output buffer
tools/pal2rgb.c:191         for (row = 0; row < imagelength; row++) {
tools/pal2rgb.c:192             if (!TIFFReadScanline(in, ibuf, row, 0))
tools/pal2rgb.c:193                 goto done;
tools/pal2rgb.c:194             pp = obuf;
tools/pal2rgb.c:195             for (x = 0; x < imagewidth; x++) { // HEAP
OVERFLOW!
tools/pal2rgb.c:196                 *pp++ = (unsigned char) rmap[ibuf[x]];
tools/pal2rgb.c:197                 *pp++ = (unsigned char) gmap[ibuf[x]];
tools/pal2rgb.c:198                 *pp++ = (unsigned char) bmap[ibuf[x]];
tools/pal2rgb.c:199             }
tools/pal2rgb.c:200             if (!TIFFWriteScanline(out, obuf, row, 0)) //
CRASH!
tools/pal2rgb.c:201                 goto done;
tools/pal2rgb.c:202         }

The process's heap memory was corrupted by COLORMAP/mage Width/Image Length of
the TIFF document. The offset of the corresponding values in the poc.tiff file
is shown below.

COLORMAP {
    R : 0x25~0x224
    G : 0x225~0x424
    B : 0x425~0x624
}

Image Width : 0x24FE
Image Length : 0x250A


 Note
You need to log in before you can comment on or make changes to this bug.

Description From jungun.baek 2017-11-29 00:50:42
The vulnerability is triggered by ./tools/pal2rgb $FILE /dev/null

The asan debug information is below:

TIFFFetchNormalTag: Warning, IO error during reading of "XResolution"; tag
ignored.
TIFFFetchNormalTag: Warning, IO error during reading of "YResolution"; tag
ignored.
sample.tiff: JPEG compression support is not configured.
TIFFSetField: /dev/null: Unknown pseudo-tag 65537.
TIFFSetField: /dev/null: Unknown pseudo-tag 65538.
sample.tiff: JPEG compression support is not configured.
=================================================================
==29649==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x611000009fe1 at pc 0x0000004f3109 bp 0x7fff697434d0 sp 0x7fff697434c8
WRITE of size 1 at 0x611000009fe1 thread T0
    #0 0x4f3108  (/home/vagrant/targets/asan/tt/tools/pal2rgb+0x4f3108)
    #1 0x7f678dc0cf44  (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #2 0x419ba5  (/home/vagrant/targets/asan/tt/tools/pal2rgb+0x419ba5)

0x611000009fe1 is located 0 bytes to the right of 225-byte region
[0x611000009f00,0x611000009fe1)
allocated by thread T0 here:
    #0 0x4c3f08  (/home/vagrant/targets/asan/tt/tools/pal2rgb+0x4c3f08)
    #1 0x4f2748  (/home/vagrant/targets/asan/tt/tools/pal2rgb+0x4f2748)
    #2 0x7f678dc0cf44  (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)

SUMMARY: AddressSanitizer: heap-buffer-overflow
(/home/vagrant/targets/asan/tt/tools/pal2rgb+0x4f3108)
Shadow bytes around the buggy address:
  0x0c227fff93a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c227fff93f0: 00 00 00 00 00 00 00 00 00 00 00 00[01]fa fa fa
  0x0c227fff9400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9410: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9420: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9430: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9440: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==29649==ABORTING

pal2rgb allocates the output buffer(obuf) too small at tools/pal2rgb.c:188.
That cause heap overflow and lead to memory corruption in TIFFSetupStrips().

(gdb) r sample.tiff /dev/null
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/vagrant/targets/asan/tt/tools/pal2rgb sample.tiff
/dev/null
TIFFFetchNormalTag: Warning, IO error during reading of "XResolution"; tag
ignored.
TIFFFetchNormalTag: Warning, IO error during reading of "YResolution"; tag
ignored.
sample.tiff: JPEG compression support is not configured.
TIFFSetField: /dev/null: Unknown pseudo-tag 65537.
TIFFSetField: /dev/null: Unknown pseudo-tag 65538.
sample.tiff: JPEG compression support is not configured.
*** Error in `/home/vagrant/targets/asan/tt/tools/pal2rgb': malloc(): memory
corruption: 0x0000000000652160 ***

Program received signal SIGABRT, Aborted.
0x00007ffff7741c37 in __GI_raise (sig=sig@entry=6) at
../nptl/sysdeps/unix/sysv/linux/raise.c:56
56    ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff7741c37 in __GI_raise (sig=sig@entry=6) at
../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff7745028 in __GI_abort () at abort.c:89
#2  0x00007ffff777e2a4 in __libc_message (do_abort=1,
    fmt=fmt@entry=0x7ffff7890310 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007ffff778c584 in malloc_printerr (ptr=0x652160,
    str=0x7ffff788c4df "malloc(): memory corruption", action=<optimized out>)
at malloc.c:4998
#4  _int_malloc (av=0x7ffff7acd760 <main_arena>, bytes=24) at malloc.c:3449
#5  0x00007ffff778dae0 in __GI___libc_malloc (bytes=24) at malloc.c:2893
#6  0x00000000004122a5 in TIFFSetupStrips (tif=tif@entry=0x651b80) at
tif_write.c:545
#7  0x00000000004124b5 in TIFFWriteCheck (tif=0x651b80, tiles=<optimized out>,
    module=0x42de50 <module> "TIFFWriteScanline") at tif_write.c:613
#8  0x0000000000412a74 in TIFFWriteScanline (tif=tif@entry=0x651b80,
buf=buf@entry=0x652070,
    row=row@entry=0, sample=sample@entry=0) at tif_write.c:56
#9  0x0000000000401dbd in main (argc=<optimized out>, argv=<optimized out>) at
pal2rgb.c:200

Affected version: 4.0.9
Latest version: 4.0.9
------- Comment #1 From jungun.baek 2017-11-29 01:44:26 -------
pal2rgb allocate output buffer to convert TIFF format. The output buffer always
uses a fixed size(225).  However, when write data to output buffer, imagewidth
and imagelength of the input TIFF file are used. it lead to heap overflow.

1) get imagewidth and imagelength from input TIFF

tools/pal2rgb.c:142     TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imagewidth);
tools/pal2rgb.c:143     TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);

2) allocate output buffer
tools/pal2rgb.c:188       obuf = (unsigned
char*)_TIFFmalloc(TIFFScanlineSize(out)); // TIFFScanlineSize(out) returns
always 225.

3) write data to output buffer
tools/pal2rgb.c:191         for (row = 0; row < imagelength; row++) {
tools/pal2rgb.c:192             if (!TIFFReadScanline(in, ibuf, row, 0))
tools/pal2rgb.c:193                 goto done;
tools/pal2rgb.c:194             pp = obuf;
tools/pal2rgb.c:195             for (x = 0; x < imagewidth; x++) { // HEAP
OVERFLOW!
tools/pal2rgb.c:196                 *pp++ = (unsigned char) rmap[ibuf[x]];
tools/pal2rgb.c:197                 *pp++ = (unsigned char) gmap[ibuf[x]];
tools/pal2rgb.c:198                 *pp++ = (unsigned char) bmap[ibuf[x]];
tools/pal2rgb.c:199             }
tools/pal2rgb.c:200             if (!TIFFWriteScanline(out, obuf, row, 0)) //
CRASH!
tools/pal2rgb.c:201                 goto done;
tools/pal2rgb.c:202         }
------- Comment #2 From jungun.baek 2017-11-29 02:28:44 -------
Created an attachment (id=819) [details]
heap overflow PoC
------- Comment #3 From jungun.baek 2017-11-29 06:33:21 -------
The process's heap memory was corrupted by COLORMAP/mage Width/Image Length of
the TIFF document. The offset of the corresponding values in the poc.tiff file
is shown below.

COLORMAP {
    R : 0x25~0x224
    G : 0x225~0x424
    B : 0x425~0x624
}

Image Width : 0x24FE
Image Length : 0x250A
------- Comment #4 From ncopa@alpinelinux.org 2017-12-07 04:42:35 -------
The following change fixes the describe behavior:

diff --git a/tools/pal2rgb.c b/tools/pal2rgb.c
index 7a57800..92d9e29 100644
--- a/tools/pal2rgb.c
+++ b/tools/pal2rgb.c
@@ -184,15 +184,17 @@ main(int argc, char* argv[])
     { unsigned char *ibuf, *obuf;
       register unsigned char* pp;
       register uint32 x;
-      ibuf = (unsigned char*)_TIFFmalloc(TIFFScanlineSize(in));
-      obuf = (unsigned char*)_TIFFmalloc(TIFFScanlineSize(out));
+      size_t ibuf_size = TIFFScanlineSize(in);
+      size_t obuf_size = TIFFScanlineSize(out);
+      ibuf = (unsigned char*)_TIFFmalloc(ibuf_size);
+      obuf = (unsigned char*)_TIFFmalloc(obuf_size);
       switch (config) {
       case PLANARCONFIG_CONTIG:
         for (row = 0; row < imagelength; row++) {
             if (!TIFFReadScanline(in, ibuf, row, 0))
                 goto done;
             pp = obuf;
-            for (x = 0; x < imagewidth; x++) {
+            for (x = 0; x < imagewidth && x < (obuf_size-3); x++) {
                 *pp++ = (unsigned char) rmap[ibuf[x]];
                 *pp++ = (unsigned char) gmap[ibuf[x]];
                 *pp++ = (unsigned char) bmap[ibuf[x]];
@@ -205,15 +207,15 @@ main(int argc, char* argv[])
         for (row = 0; row < imagelength; row++) {
             if (!TIFFReadScanline(in, ibuf, row, 0))
                 goto done;
-            for (pp = obuf, x = 0; x < imagewidth; x++)
+            for (pp = obuf, x = 0; x < imagewidth && x < obuf_size; x++)
                 *pp++ = (unsigned char) rmap[ibuf[x]];
             if (!TIFFWriteScanline(out, obuf, row, 0))
                 goto done;
-            for (pp = obuf, x = 0; x < imagewidth; x++)
+            for (pp = obuf, x = 0; x < imagewidth && x < obuf_size; x++)
                 *pp++ = (unsigned char) gmap[ibuf[x]];
             if (!TIFFWriteScanline(out, obuf, row, 0))
                 goto done;
-            for (pp = obuf, x = 0; x < imagewidth; x++)
+            for (pp = obuf, x = 0; x < imagewidth && x < obuf_size; x++)
                 *pp++ = (unsigned char) bmap[ibuf[x]];
             if (!TIFFWriteScanline(out, obuf, row, 0))
                 goto done;


But the pal2rgb stil segfaults. new backtrace:

Core was generated by `pal2rgb /home/ncopa/Downloads/poc.tiff out.tiff'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000065eb6f74f534 in jpeg_abort () from /usr/lib/libjpeg.so.8
(gdb) bt
#0  0x000065eb6f74f534 in jpeg_abort () from /usr/lib/libjpeg.so.8
#1  0x000065eb6f9c26b7 in TIFFjpeg_abort (sp=sp@entry=0xdbd8738e7c0)
    at tif_jpeg.c:416
#2  0x000065eb6f9c3f8c in JPEGPreDecode (tif=0x65eb6fc06900, s=<optimized out>)
    at tif_jpeg.c:1114
#3  0x000065eb6f9d4305 in TIFFSeek (sample=0, row=54, tif=0x65eb6fc06900)
    at tif_read.c:379
#4  TIFFReadScanline (tif=0x65eb6fc06900, buf=0xdbd8738ef40, row=54, 
    sample=<optimized out>) at tif_read.c:446
#5  0x00000dbd8718c5fc in main (argc=<optimized out>, argv=<optimized out>)
    at pal2rgb.c:194


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/43322.zip