Invalid memory access vulnerability in the function adv_png_unfilter_8( ) – advancecomp-2.1
Loginsoft-2018-1050
February 13, 2019
CVE Number
CVE-2019-8383
CWE
CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
Product Details
AdvanceCOMP contains recompression utilities for your .zip archives,.png images, .mng video clips and .gz files.
URL: https://sourceforge.net/projects/advancemame/
Vulnerable Versions
2.1
Vulnerability Details
During our research on advancecomp, we found invalid memory address in function adv_png_unfilter_8 ( ) at file png.c. The same can be triggered by sending a crafted abc file to the binary. It allows an attacker to cause Denial of Service (Segmentation fault) or possibly have unspecified other impact when a victim opens a specially crafted file.
SYNOPSIS
As per our research we observed that the vulnerability exists in function adv_png_unfilter_8( ) at file png.c . The function adv_png_read_rns( ),which reads an image from memory which is in png format and invokes the function adv_png_read_ihdr (),which reads a part of chunk image from PNG_CN_IHDR to the chunk from the main in PNG_CN_IEND . This function invokes adv_png_unfilter_8( ) which unfilters a 8 bit image of width, height, data and size of row. When a crafted file is passed to the binary advpng in function adv_png_unfilter_8( ) at unsigned char f = *p++;
p += width;
The value of width is being assigned to p. The value of f is 0 and p is having a value at address while incrementing the p value the vulnerability is being triggered as invalid memory access.
Vulnerable code
for(i=0;i<height;++i) { unsigned char f = *p++; if (f == 0) { /* none */ p += width; }
Analysis
277 unsigned char f = *p++; [ Legend: Modified register | Code | Heap | Stack | String ] ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]──── $rax : 0x80661b7d $rbx : 0x0 $rcx : 0x8000008d $rdx : 0x80661b7e $rsp : 0x7fffffffd7d0 → 0x00007fffffffd910 → 0x00007fffffffd9e0 → 0x00007fffffffda90 → 0x00007fffffffdb70 → 0x00007fffffffdc60 → 0x00007fffffffdce0 → 0x00007fffffffddb0 $rbp : 0x7fffffffd7d0 → 0x00007fffffffd910 → 0x00007fffffffd9e0 → 0x00007fffffffda90 → 0x00007fffffffdb70 → 0x00007fffffffdc60 → 0x00007fffffffdce0 → 0x00007fffffffddb0 $rsi : 0x78 $rdi : 0x8000008c $rip : 0x40c5c7 → movzx eax, BYTE PTR [rax] $r8 : 0x65ffa0 → 0x0000000000000000 $r9 : 0x1 $r10 : 0x8b8 $r11 : 0x7ffff6fca4f0 → push r13 $r12 : 0x402fe0 → xor ebp, ebp $r13 : 0x7fffffffdee0 → 0x0000000000000005 $r14 : 0x0 $r15 : 0x0 $eflags: [CARRY parity ADJUST zero SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification] $fs: 0x0000 $cs: 0x0033 $gs: 0x0000 $es: 0x0000 $ds: 0x0000 $ss: 0x002b ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]──── 0x00007fffffffd7d0│+0x00: 0x00007fffffffd910 → 0x00007fffffffd9e0 → 0x00007fffffffda90 → 0x00007fffffffdb70 → 0x00007fffffffdc60 → 0x00007fffffffdce0 → 0x00007fffffffddb0 ← $rsp, $rbp 0x00007fffffffd7d8│+0x08: 0x000000000040d8d0 → jmp 0x40db14 0x00007fffffffd7e0│+0x10: 0xb7b6b5b4b3b2b1b0 0x00007fffffffd7e8│+0x18: 0x000000000065fe00 → 0x780000008c000080 0x00007fffffffd7f0│+0x20: 0x000000000065fc60 → 0x00007fff00000001 0x00007fffffffd7f8│+0x28: 0x00007fffffffda50 → 0x8000008d00000000 0x00007fffffffd800│+0x30: 0x00007fffffffda68 → 0x0000000000000000 0x00007fffffffd808│+0x38: 0x00007fffffffda4c → 0x000000000000007e ("~"?) ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386:x86-64 ]──── 0x40c5b7 test BYTE PTR [rdx], 0x0 0x40c5ba add BYTE PTR [rax-0x75], cl 0x40c5bd rex.RB movabs al, ds:0xa055894801508d48 → 0x40c5c7 movzx eax, BYTE PTR [rax] 0x40c5ca mov BYTE PTR [rbp-0x41], al 0x40c5cd cmp BYTE PTR [rbp-0x41], 0x0 0x40c5d1 jne 0x40c5df 0x40c5d3 mov eax, DWORD PTR [rbp-0x54] 0x40c5d6 add QWORD PTR [rbp-0x60], rax ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ source:lib/png.c+277 ]──── 272 void adv_png_unfilter_8(unsigned width, unsigned height, unsigned char* p, unsigned line) 273 { 274 unsigned i, j; 275 276 for(i=0;i<height;++i) { // f=0x0, p=0x00007fffffffd770 → 0x0000000080661b7e → 277 unsigned char f = *p++; 278 279 if (f == 0) { /* none */ 280 p += width; 281 } else if (f == 1) { /* sub */ 282 ++p; ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]──── [#0] Id 1, Name: "advpng", stopped, reason: SIGSEGV ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]──── [#0] 0x40c5c7 → Name: adv_png_unfilter_8(width=0x8000008c, height=0x78, p=0x80661b7e , line=0x8000008d) [#1] 0x40d8d0 → Name: adv_png_read_ihdr(pix_width=0x7fffffffda44, pix_height=0x7fffffffda48, pix_pixel=0x7fffffffda40, dat_ptr=0x7fffffffda58, dat_size=0x7fffffffda3c, pix_ptr=0x7fffffffda70, pix_scanline=0x7fffffffda54, pal_ptr=0x7fffffffda60, pal_size=0x7fffffffda4c, rns_ptr=0x7fffffffda68, rns_size=0x7fffffffda50, f=0x65fc60, data=0x65fe00 "\200", data_size=0xd) [#2] 0x40dc94 → Name: adv_png_read_rns(pix_width=0x7fffffffda44, pix_height=0x7fffffffda48, pix_pixel=0x7fffffffda40, dat_ptr=0x7fffffffda58, dat_size=0x7fffffffda3c, pix_ptr=0x7fffffffda70, pix_scanline=0x7fffffffda54, pal_ptr=0x7fffffffda60, pal_size=0x7fffffffda4c, rns_ptr=0x7fffffffda68, rns_size=0x7fffffffda50, f=0x65fc60) [#3] 0x4037dd → Name: convert_f(f_in=0x65fc60, f_out=0x65fd30) [#4] 0x403a62 → Name: convert_inplace(path="$POC") [#5] 0x404209 → Name: rezip_single(file="id:000000,sig:11,src:000000,op:flip1,pos:16", total_0=@0x7fffffffdc90, total_1=@0x7fffffffdc98) [#6] 0x4045a1 → Name: rezip_all(argc=0x1, argv=0x7fffffffdf08) [#7] 0x404df0 → Name: process(argc=0x5, argv=0x7fffffffdee8) [#8] 0x404fba → Name: main(argc=0x5, argv=0x7fffffffdee8)
Tested environment
64-bit ubuntu 16.04 LTS
Proof of Concept
- ./advpng -z -1 –f $POC
Timeline
Vendor Disclosure: 03-01-2019
Public Disclosure: 13-02-2019
Credit
Discovered by ACE Team – Loginsoft