rockcarry / ffjpeg

a simple jpeg codec.
GNU General Public License v3.0
106 stars 46 forks source link

Heap-buffer-overflows in jfif_decode() at jfif.c:516 and 546 #20

Closed 14isnot40 closed 4 years ago

14isnot40 commented 4 years ago

Describe the bug A heap-based buffer overflow was discovered in ffjpeg, during the src of memcpy () points to an inaccessible address. The issue is being triggered in the function jfif_decode() at jfif.c:516.

To Reproduce Steps to reproduce the behavior:

  1. Compile ffjpeg with address sanitizer
  2. execute command
    ffjpeg -d $poc

    poc can be found here.

Expected behavior An attacker can exploit this vulnerability by submitting a malicious jpeg that exploits this issue. This will result in a Denial of Service (DoS) and when the application attempts to process the file.

Screenshots ASAN Reports

==115406==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7ffff3aff900 at pc 0x7ffff6ef6904 bp 0x7fffffffd580 sp 0x7fffffffcd28
WRITE of size 32 at 0x7ffff3aff900 thread T0
    #0 0x7ffff6ef6903 in __asan_memcpy (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x8c903)
    #1 0x405642 in jfif_decode /home/test/Desktop/evaulation/ffjpeg/ffjpeg/src/jfif.c:516
    #2 0x4011b0 in main /home/test/Desktop/evaulation/ffjpeg/ffjpeg/src/ffjpeg.c:24
    #3 0x7ffff6ac082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #4 0x400f78 in _start (/home/test/Desktop/evaulation/ffjpeg/ffjpeg/src/ffjpeg+0x400f78)

0x7ffff3aff900 is located 256 bytes to the right of 2097152-byte region [0x7ffff38ff800,0x7ffff3aff800)
allocated by thread T0 here:
    #0 0x7ffff6f02602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x404c0e in jfif_decode /home/test/Desktop/evaulation/ffjpeg/ffjpeg/src/jfif.c:442
    #2 0x4011b0 in main /home/test/Desktop/evaulation/ffjpeg/ffjpeg/src/ffjpeg.c:24
    #3 0x7ffff6ac082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-buffer-overflow ??:0 __asan_memcpy
Shadow bytes around the buggy address:
  0x10007e757ed0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e757ee0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e757ef0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e757f00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e757f10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x10007e757f20:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e757f30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e757f40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e757f50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e757f60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e757f70: 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
==115406==ABORTING

gdb debug

Breakpoint 13, 0x000000000040563e in jfif_decode (ctxt=0x61500000fd00, pb=0x7fffffffd9d0) at jfif.c:516
516                            memcpy(idst, isrc, 8 * sizeof(int));
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x00007ffff3aff900  →  0x0000000000000000
$rbx   : 0x00007fffffffd960  →  0x00007fffffffd9b0  →  0x0000000041b58ab3
$rcx   : 0x00007fffffffd880  →  0xf8000000f8000000
$rdx   : 0x20              
$rsp   : 0x00007fffffffd590  →  0x00007fffffffd9d0  →  0x0000000000000000
$rbp   : 0x00007fffffffd980  →  0x00007fffffffda30  →  0x000000000040e630  →  <__libc_csu_init+0> push r15
$rsi   : 0x00007fffffffd880  →  0xf8000000f8000000
$rdi   : 0x00007ffff3aff900  →  0x0000000000000000
$rip   : 0x000000000040563e  →  <jfif_decode+4547> call 0x400e20 <memcpy@plt>
$r8    : 0x7               
$r9    : 0x7               
$r10   : 0x0               
$r11   : 0x7               
$r12   : 0x00000ffffffffacc  →  0x0000000000000000
$r13   : 0x00007fffffffd660  →  0x0000000041b58ab3
$r14   : 0x00007fffffffd660  →  0x0000000041b58ab3
$r15   : 0x0               
$eflags: [CARRY PARITY ADJUST zero SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffd590│+0x0000: 0x00007fffffffd9d0  →  0x0000000000000000     ← $rsp
0x00007fffffffd598│+0x0008: 0x000061500000fd00  →  0x0000ffff0000fff4
0x00007fffffffd5a0│+0x0010: 0x00000000ffffffff  →  0x0000000000000000
0x00007fffffffd5a8│+0x0018: 0x00000000f6e73ce0  →  0x0000000000000000
0x00007fffffffd5b0│+0x0020: 0x00007fff00000003
0x00007fffffffd5b8│+0x0028: 0x0000000000000000
0x00007fffffffd5c0│+0x0030: 0x0000000f00000001  →  0x0000000000000000
0x00007fffffffd5c8│+0x0038: 0xffffffff0000000a
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x405633 <jfif_decode+4536> mov    edx, 0x20
     0x405638 <jfif_decode+4541> mov    rsi, rcx
     0x40563b <jfif_decode+4544> mov    rdi, rax
 →   0x40563e <jfif_decode+4547> call   0x400e20 <memcpy@plt>
   ↳    0x400e20 <memcpy@plt+0>   jmp    QWORD PTR [rip+0x210262]        # 0x611088 <memcpy@got.plt>
        0x400e26 <memcpy@plt+6>   push   0xe
        0x400e2b <memcpy@plt+11>  jmp    0x400d30
        0x400e30 <__asan_report_store4@plt+0> jmp    QWORD PTR [rip+0x21025a]        # 0x611090 <__asan_report_store4@got.plt>
        0x400e36 <__asan_report_store4@plt+6> push   0xf
        0x400e3b <__asan_report_store4@plt+11> jmp    0x400d30
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
memcpy@plt (
   $rdi = 0x00007ffff3aff900 → 0x0000000000000000,
   $rsi = 0x00007fffffffd880 → 0xf8000000f8000000,
   $rdx = 0x0000000000000020,
   $rcx = 0x00007fffffffd880 → 0xf8000000f8000000,
   $r8 = 0x0000000000000007,
   $r9 = 0x0000000000000007
)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "ffjpeg", stopped, reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x40563e → jfif_decode(ctxt=0x61500000fd00, pb=0x7fffffffd9d0)
[#1] 0x4011b1 → main(argc=0x3, argv=0x7fffffffdb18)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  p idst
$30 = (int *) 0x7ffff3aff900
gef➤  p isrc
$31 = (int *) 0x7fffffffd880
gef➤  x /10xb 0xf8000000f8000000,
A syntax error in expression, near `'.
gef➤  x /10xb 0xf8000000f8000000 
0xf8000000f8000000:    Cannot access memory at address 0xf8000000f8000000
gef➤  p i 
$32 = 0x3
gef➤  p h
$33 = 0x0
gef➤  p v
$34 = 0x1
gef➤  p c
$35 = 0x0
gef➤  p mcui
$36 = 0x0

Possible causes of vulnerabilitie The 'memcpy' function copies from an invalid address pointed by 'isrc', resulting to a seg fault.

idst = yuv_datbuf[c] + y * yuv_stride[c] + x;

isrc = du;

for (i=0; i<8; i++) {

    memcpy(idst, isrc, 8 * sizeof(int));

    idst += yuv_stride[c];

    isrc += 8;

System (please complete the following information):

rockcarry commented 4 years ago

a new commit acc868ddda879d9b147086efb483130bafdd86b8 fix this issue. @14isnot40 please check and test again.

14isnot40 commented 4 years ago

a new commit acc868d fix this issue. @14isnot40 please check and test again.

Tested and patched, thanks for your work