Project: openjpeg (uclouvain/openjpeg), language: c++
Vulnerability instance: openjpeg.cve-2016-3182
Sanitizer: address

================= Bug Report (1/2) ==================
## Source: Red Hat Bugzilla
## URL: https://bugzilla.redhat.com/show_bug.cgi?id=1317826
## Description:
Bugzilla ID: 1317826
Title: CVE-2016-3182 openjpeg: Heap corruption in opj_free function

Description
Adam Mariš 2016-03-15 10:17:38 UTC
Double free or heap corruption vulnerability was found in opj_free function triggered by specially crafted JPEG2000 image file was found in openjpeg 2016.03.14.

CVE request (contains reproducer):

http://seclists.org/oss-sec/2016/q1/631


Comments:
Comment 1
Adam Mariš 2016-03-15 10:20:00 UTC
Created mingw-openjpeg2 tracking bugs for this issue:

Affects: fedora-all [bug 1317831]

---

Comment 2
Adam Mariš 2016-03-15 10:20:05 UTC
Created openjpeg2 tracking bugs for this issue:

Affects: fedora-all [bug 1317830]
Affects: epel-all [bug 1317832]

---

Comment 3
Andrej Nemec 2016-03-17 08:23:14 UTC
CVE assignment:

http://seclists.org/oss-sec/2016/q1/667

---

Comment 4
Sandro Mani 2016-05-04 11:43:50 UTC
Patch: https://github.com/uclouvain/openjpeg/commit/ad593c9e0622e0d8d87228e67e4dbd36243ffd22

---

Comment 5
Fedora Update System 2016-07-14 14:51:36 UTC
openjpeg2-2.1.1-1.fc24 has been pushed to the Fedora 24 stable repository. If problems still persist, please make note of it in this bug report.

================= Bug Report (2/2) ==================
## Source: GitHub Issue
## URL: https://github.com/uclouvain/openjpeg/issues/725
## Description:
Issue: uclouvain/openjpeg#725
Title: CVE-2016-3182 Heap Corruption in opj_free function
State: closed
Created by: trylab
Created at: 2016-03-16 10:05:18+00:00
Labels: bug, Priority-Critical

Issue Body:
# Vulnerability Details

According to AddressSanitizer's output message, the Out-of-Bounds read occurred in function color_esycc_to_rgb. However, there must be also an Out-of-Bounds write circumstance since an exception will be throwed when freeing the heap buffer.
- AddressSanitizer output the following exception information.

```
==116473==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61300000e000 
at pc 0x0000005309ef bp 0x7fffb332de20 sp 0x7fffb332de18
READ of size 4 at 0x61300000e000 thread T0
    #0 0x5309ee in color_esycc_to_rgb openjpeg/src/bin/common/color.c:760:37
    #1 0x4f215c in main openjpeg/src/bin/jp2/opj_decompress.c:1381:4
    #2 0x7f50d46dd82f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291
    #3 0x41a978 in _start (openjpeg/bin/opj_decompress+0x41a978)

0x61300000e000 is located 0 bytes to the right of 384-byte region [0x61300000de80,0x61300000e000)
allocated by thread T0 here:
    #0 0x4bac30 in calloc (openjpeg/bin/opj_decompress+0x4bac30)
    #1 0x7f50d5fd9764 in opj_calloc openjpeg/src/lib/openjp2/opj_malloc.c:203:10
    #2 0x7f50d5f4ce7a in opj_j2k_update_image_data openjpeg/src/lib/openjp2/j2k.c:8212:62
    #3 0x7f50d5f4c886 in opj_j2k_decode_tiles openjpeg/src/lib/openjp2/j2k.c:9752:23
    #4 0x7f50d5f153fd in opj_j2k_exec openjpeg/src/lib/openjp2/j2k.c:7341:41
    #5 0x7f50d5f2844e in opj_j2k_decode openjpeg/src/lib/openjp2/j2k.c:9943:15
    #6 0x7f50d5f636ce in opj_jp2_decode openjpeg/src/lib/openjp2/jp2.c:1487:8
    #7 0x7f50d5f80356 in opj_decode openjpeg/src/lib/openjp2/openjpeg.c:412:10
    #8 0x4f1627 in main openjpeg/src/bin/jp2/opj_decompress.c:1330:10
    #9 0x7f50d46dd82f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291

SUMMARY: AddressSanitizer: heap-buffer-overflow openjpeg/src/bin/common/color.c:760:37 in color_esycc_to_rgb
Shadow bytes around the buggy address:
  0x0c267fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff9bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c267fff9be0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c267fff9bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c267fff9c00:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff9c50: 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
==116473==ABORTING
```
- GDB backtrace

If compile openjpeg with gcc and **do not** specify `-fsanitize=address`, a heap corruption will be occurred.

```
[INFO] Stream reached its end !
WARNING -> [PGM file] Only the first component
           is written to the file
[INFO] Generated Outfile image.pgm

Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x1f00000000) at malloc.c:2952
2952    malloc.c: No such file or directory.
(gdb) bt
#0  __GI___libc_free (mem=0x1f00000000) at malloc.c:2952
#1  0x00007ffff7bc775d in opj_free (ptr=0x1f00000000) at opj_gcc/src/lib/openjp2/opj_malloc.c:238
#2  0x00007ffff7bc50e2 in opj_tcd_free_tile (p_tcd=0x626f00) at opj_gcc/src/lib/openjp2/tcd.c:1508
#3  0x00007ffff7bc2d1d in opj_tcd_destroy (tcd=0x626f00) at opj_gcc/src/lib/openjp2/tcd.c:616
#4  0x00007ffff7ba23e5 in opj_j2k_destroy (p_j2k=0x620440) at opj_gcc/src/lib/openjp2/j2k.c:7541
#5  0x00007ffff7bb09d5 in opj_jp2_destroy (jp2=0x620380) at opj_gcc/src/lib/openjp2/jp2.c:2778
#6  0x00007ffff7bb4515 in opj_destroy_codec (p_codec=0x6202d0) at opj_gcc/src/lib/openjp2/openjpeg.c:845
#7  0x000000000040682d in main (argc=5, argv=0x7fffffffdeb8) at opj_gcc/src/bin/jp2/opj_decompress.c:1558

```
# Credit

Ke Liu of Tencent's Xuanwu LAB



Comments:
Comment by mayeut on 2016-04-21 16:55:57+00:00:
ASan report:

```
==89072==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61300000e000 at pc 0x00010b39cfe2 bp 0x7fff54884680 sp 0x7fff54884678
READ of size 4 at 0x61300000e000 thread T0
    #0 0x10b39cfe1 in color_esycc_to_rgb /Users/Matt/Dev/OpenJpegNew/openjpeg/src/bin/common/color.c:760:37
    #1 0x10b37c1bb in main /Users/Matt/Dev/OpenJpegNew/openjpeg/src/bin/jp2/opj_decompress.c:1381:4
    #2 0x7fff9af465ac  (/usr/lib/system/libdyld.dylib+0x35ac)
    #3 0x4  (<unknown module>)
```


---

Comment by szukw000 on 2016-04-24 19:50:03+00:00:
@mayeut ,

The file heap_corruption.jp2 is interesting. It is

  Created by OpenJPEG version 2.1.0

It seems to be possible to write any nonsense values and
'OpenJPEG version 2.1.0' accepts this nonsense.

bin/opj_flviewer /usb_c/IMG/JP2/heap_corruption.jp2
color.cxx:1088: COLOR_esycc_to_rgb
        CAN NOT CONVERT 4 components.
color.cxx:1098: COLOR_esycc_to_rgb
        CAN NOT CONVERT DX(1,15,1) DY(1,1,1)

FILE(heap_corruption.jp2)
LENG(414)
 **name(ftyp)**
   brand(jp2 ) minv(0)
   CL[0](jp2 )
**BOX name(ihdr) len(22)**
    w(32) h(32) nc(4) bpc(255)
    signed(1) depth(128)
    compress(7) unknown_c(0) ipr(0)
 **BOX name(bpcc) len(12)**
    free(4) nr_components(4)
     bpcc[0](4)
     bpcc[1](4)
     bpcc[2](4)
     bpcc[3](0)
**BOX name(colr) len(15)**
    meth(1) prec(0) approx(0) enumcs[24]e-sYCC
**BOX name(cdef) len(34)**
------------ start cdef -------------------
[0]c(0) typ(0) asoc(2)
[1]c(1) typ(0) asoc(3)
[2]c(2) typ(25) asoc(3)
[3]c(3) typ(1) asoc(0)
------------ end cdef ---------------------
**BOX name(jp2c)**
[0]marker(0xff4f) soc len(0)

[2]marker(0xff51) siz len(50)

```
capabilities(0)\[extended: 0\]
x(0 : 32) y(0 : 32)
xt(0 : 32) yt(0 : 32)
IMAGE w(32) h(32) TILE w(32) h(32)
nr_components(4)
  component[0] signed(0) prec(5) hsep(15) vsep(1)
  component[1] signed(0) prec(5) hsep(1) vsep(1)
  component[2] signed(0) prec(5) hsep(1) vsep(1)
  component[3] signed(0) prec(1) hsep(1) vsep(1)
```

[54]marker(0xff52) cod len 12
    prog_order 0
    nr_layers 1
    multi_comp_transform 1
Scod 0
       entropy_coder 0
      use_sop_marker 0
      use_eph_marker 0
      num_resolutions 6
     code_block_width 4
    code_block_height 4
     code_block_style 0
       transformation 1 (5-3 reversible)

```
[0]precinct_w 15
[0]precinct_h 15
[1]precinct_w 15
[1]precinct_h 15
[2]precinct_w 15
[2]precinct_h 15
[3]precinct_w 15
[3]precinct_h 15
[4]precinct_w 15
[4]precinct_h 15
[5]precinct_w 15
[5]precinct_h 15
```

[68]marker(0xff5c) qcd  len(19)

[89]marker(0xff64) com  len(37)
      General use (ISO 8859-1 (latin-1) values)
      Created by OpenJPEG version 2.1.0

[128]marker(0xff90) sot len(10)
------- Psot (153) --------
    sot  tile_nr(0) Psot(153) TPsot(0) TNsot(1)

[140]marker(0xff93) sod len(139)

[281]marker(0xffd9) eoc  len(0)


Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
mkdir -p build
cd build
cmake ..
make clean -s -j$(nproc)
make -j$(nproc) -s

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make cmake g++
RUN git clone https://github.com/uclouvain/openjpeg openjpeg
RUN git -C openjpeg checkout 788dff0a3650f8897eaafe951512a4bae63808dd
WORKDIR $SRC/openjpeg
COPY build.sh $SRC/

Additional files: