Closed gcode-importer closed 9 years ago
Dear OpenJpeg developers,
we identified two heap overflow vulnerabilities in OpenJpeg 1.5.2. Attached to this
message there are two proof of concept images which will help you confirm and address
the vulnerabilities.
Please confirm at your earliest convenience that you have received this vulnerability
report. We will gladly work with you so you can successfully confirm and reproduce
this issue.
Also note that this bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically become visible
to the public.
We’ll be tracking this on:
https://code.google.com/p/google-security-research/issues/detail?id=105
Don’t hesitate to let us know if you have any questions!
Details
For both bugs I used j2k_dump from the precompiled 32-bit package that can be downloaded
from Sourceforge (http://sourceforge.net/projects/openjpeg.mirror/files/1.5.2/openjpeg-1.5.2-Linux-i386.tar.gz/download).
Heap Overflow in dwt_interleave_h
The bug is triggered in case that h->sn in dwt_interleave_h() receives a dwt_t object
with a negative value in the sn field, causing the “while(--i)” loop to overflow h->mem:
static void dwt_interleave_h(dwt_t* h, int *a) {
int *ai = a;
int *bi = h->mem + h->cas;
int i = h->sn;
printf("i: %d\n", i);
while( i-- ) {
*bi = *(ai++);
bi += 2;
}
Taking a look inside gdb:
$ r -i dwt_interleave_h.jp2
Program received signal SIGSEGV, Segmentation fault.
[--------------registers--------------]
EAX: 0x2454 ('T$')
EBX: 0xf7fd8124 --> 0x2300c
ECX: 0x31ff36ff
EDX: 0x810ad60 --> 0xffffffcc
ESI: 0x810b900 --> 0x0
EDI: 0x0
EBP: 0xffffffff
ESP: 0xffff9800 --> 0xf7fba539 (<dwt_decode+153>: mov edi,DWORD PTR [esp+0x38])
EIP: 0xf7fba5fb (<dwt_decode+347>: mov DWORD PTR [edx+eax*8],ecx)
EFLAGS: 0x10217 (CARRY PARITY ADJUST zero sign trap INTERRUPT direction overflow)
[--------------code--------------]
0xf7fba5f2 <dwt_decode+338>: mov DWORD PTR [esp+0x20],ecx
0xf7fba5f6 <dwt_decode+342>: xchg ax,ax
0xf7fba5f8 <dwt_decode+344>: mov ecx,DWORD PTR [esi+eax*4]
=> 0xf7fba5fb <dwt_decode+347>: mov DWORD PTR [edx+eax*8],ecx
0xf7fba5fe <dwt_decode+350>: add eax,0x1
0xf7fba601 <dwt_decode+353>: cmp eax,ebp
0xf7fba603 <dwt_decode+355>: jne 0xf7fba5f8 <dwt_decode+344>
0xf7fba605 <dwt_decode+357>: mov ecx,DWORD PTR [esp+0x20]
Stopped reason: SIGSEGV
0xf7fba5fb in dwt_interleave_h (a=0x810b900, h=0xffff9840) at /tmp/openjpeg_release/openjpeg/libopenjpeg/dwt.c:187
187 in /tmp/openjpeg_release/openjpeg/libopenjpeg/dwt.c
$ bt
#0 0xf7fba5fb in dwt_interleave_h (a=0x810b900, h=0xffff9840) at /tmp/openjpeg_release/openjpeg/libopenjpeg/dwt.c:187
#1 dwt_decode_tile (numres=<optimized out>, tilec=0x81019b8, dwt_1D=<optimized out>)
at /tmp/openjpeg_release/openjpeg/libopenjpeg/dwt.c:548
#2 dwt_decode (tilec=0x81019b8, numres=0x1d, numres@entry=0x1f) at /tmp/openjpeg_release/openjpeg/libopenjpeg/dwt.c:383
#3 0xf7fcff45 in tcd_decode_tile (tcd=tcd@entry=0x8101618, src=0x8100f58, len=0x6ba,
tileno=0x0, cstr_info=0x0) at /tmp/openjpeg_release/openjpeg/libopenjpeg/tcd.c:1444
#4 0xf7fbcd1b in j2k_read_eoc (j2k=0x80fc088) at /tmp/openjpeg_release/openjpeg/libopenjpeg/j2k.c:1695
#5 0xf7fbe0a9 in j2k_decode (j2k=0x80fc088, cio=cio@entry=0x80fc150, cstr_info=cstr_info@entry=0x0)
at /tmp/openjpeg_release/openjpeg/libopenjpeg/j2k.c:2027
#6 0xf7fc0f6a in opj_jp2_decode (jp2=0x80fc028, cio=cio@entry=0x80fc150, cstr_info=cstr_info@entry=0x0)
at /tmp/openjpeg_release/openjpeg/libopenjpeg/jp2.c:841
#7 0xf7fc3987 in opj_decode_with_info (dinfo=dinfo@entry=0x80fc008, cio=cio@entry=0x80fc150,
cstr_info=cstr_info@entry=0x0) at /tmp/openjpeg_release/openjpeg/libopenjpeg/openjpeg.c:168
#8 0xf7fc39eb in opj_decode (dinfo=dinfo@entry=0x80fc008, cio=cio@entry=0x80fc150)
at /tmp/openjpeg_release/openjpeg/libopenjpeg/openjpeg.c:157
#9 0x080550e0 in main (argc=0x3, argv=0xffffcc74) at /tmp/openjpeg_release/openjpeg/applications/codec/j2k_dump.c:507
#10 0xf7daea83 in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6
#11 0x08055389 in _start ()
$ info proc mappings
process 21130
Mapped address spaces:
Start Addr End Addr Size Offset objfile
[...]
0x80fc000 0x811d000 0x21000 0x0 [heap]
0xf7d94000 0xf7d95000 0x1000 0x0
[...]
“mov DWORD PTR [edx+eax*8],ecx” is writing past the end of the heap in 0x811d000
Heap Overflow in dwt_decode_real/v4dwt_interleave_h
The bug is in v4dwt_interleave_h() where we have some control over the w->sn value
and can therefore overflow w->wavelet.
static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, int size){
float* restrict bi = (float*) (w->wavelet + w->cas);
int count = w->sn;
[...]
/* Slow code path */
for(i = 0; i < count; ++i){
int j = i;
bi[i*8 ] = a[j];
j += x;
if(j > size) continue;
bi[i*8 + 1] = a[j];
j += x;
if(j > size) continue;
bi[i*8 + 2] = a[j];
j += x;
if(j > size) continue;
bi[i*8 + 3] = a[j];
}
With the attached proof of concept, the wavelet is allocated with 105 elements (1680
bytes) but we can specify a count equal to 100 via w->sn, which allows us to overwrite
up to the position 803.
The overflow happens right after the alloc, so we’re not overwriting other objects
on the heap at this point. This causes a less obvious crash that with the previous
bug, so it’s better to take a look with valgrind:
$ valgrind ./j2k_dump -i v4dwt_interleave_h.j2k
[...]
[INFO] tile 1 of 1
[INFO] - tiers-1 took 0.056034 s
==19760== Invalid write of size 4
==19760== at 0x403BDCD: v4dwt_interleave_h (/tmp/openjpeg_release/openjpeg/libopenjpeg/dwt.c:589)
==19760== by 0x403D012: dwt_decode_real (/tmp/openjpeg_release/openjpeg/libopenjpeg/dwt.c:821)
==19760== by 0x4051EE0: tcd_decode_tile (/tmp/openjpeg_release/openjpeg/libopenjpeg/tcd.c:1446)
==19760== by 0x403ED1A: j2k_read_eoc (/tmp/openjpeg_release/openjpeg/libopenjpeg/j2k.c:1695)
==19760== by 0x40400A8: j2k_decode (/tmp/openjpeg_release/openjpeg/libopenjpeg/j2k.c:2027)
==19760== by 0x4045966: opj_decode_with_info (/tmp/openjpeg_release/openjpeg/libopenjpeg/openjpeg.c:164)
==19760== by 0x40E3A82: (below main) (in /lib/i386-linux-gnu/libc-2.19.so)
==19760== Address 0x42a53f0 is 16 bytes after a block of size 1,680 alloc'd
==19760== at 0x402BC74: memalign (valgrind/coregrind/m_replacemalloc/vg_replace_malloc.c:726)
==19760== by 0x403CD19: dwt_decode_real (/tmp/openjpeg_release/openjpeg/libopenjpeg/dwt.c:786)
==19760== by 0x4051EE0: tcd_decode_tile (/tmp/openjpeg_release/openjpeg/libopenjpeg/tcd.c:1446)
==19760== by 0x403ED1A: j2k_read_eoc (/tmp/openjpeg_release/openjpeg/libopenjpeg/j2k.c:1695)
==19760== by 0x40400A8: j2k_decode (/tmp/openjpeg_release/openjpeg/libopenjpeg/j2k.c:2027)
==19760== by 0x4045966: opj_decode_with_info (/tmp/openjpeg_release/openjpeg/libopenjpeg/openjpeg.c:164)
==19760== by 0x40E3A82: (below main) (in /lib/i386-linux-gnu/libc-2.19.so)
Reported by detonin on 2014-09-15 12:53:44
Reported by detonin on 2014-09-15 12:54:59
Reported by detonin on 2014-09-17 09:03:20
datasets have been uploaded r2876
Reported by malaterre on 2014-09-17 09:04:51
Reported by detonin on 2014-09-17 09:15:40
Trying to reproduce on trunk r2958 before looking branch 1.5
ASan build MacOS X64 :
./bin/opj_decompress -i ../../data/input/nonregression/dwt_interleave_h.gsr105.jp2
-o 0.bmp
==9834==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x03503368 at pc 0x007b082a
bp 0xbff7e1a8 sp 0xbff7e1a4
READ of size 4 at 0x03503368 thread T0
#0 0x7b0829 in opj_dwt_decode_1_ /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/dwt.c:313:29
#1 0x7acd26 in opj_dwt_decode_1 /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/dwt.c:329:2
#2 0x7ac8e0 in opj_dwt_decode_tile /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/dwt.c:596:4
#3 0x7ac3c0 in opj_dwt_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/dwt.c:475:9
#4 0x81c4d7 in opj_tcd_dwt_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/tcd.c:1629:31
#5 0x81bf3b in opj_tcd_decode_tile /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/tcd.c:1318:20
#6 0x7c8e47 in opj_j2k_decode_tile /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/j2k.c:7914:15
#7 0x7de2f7 in opj_j2k_decode_tiles /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/j2k.c:9428:23
#8 0x7c4df7 in opj_j2k_exec /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/j2k.c:7292:41
#9 0x7ce8e3 in opj_j2k_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/j2k.c:9619:15
#10 0x7e5adf in opj_jp2_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/jp2.c:1406:8
#11 0x7f2133 in opj_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/openjpeg.c:412:10
#12 0x831d9 in main /Users/Matt/Dev/OpenJpeg/issue/src/bin/jp2/opj_decompress.c:1269:10
#13 0x912416d8 in start (/usr/lib/system/libdyld.dylib+0x36d8)
#14 0x4 (<unknown module>)
0x03503368 is located 8 bytes to the left of 136-byte region [0x03503370,0x035033f8)
allocated by thread T0 here:
#0 0x2ebdba in wrap_malloc (/Users/Matt/Dev/llvm-clang-3.5.0-macosx-apple-darwin/lib/clang/3.5.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x2fdba)
#1 0x7ac5c2 in opj_dwt_decode_tile /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/dwt.c:572:2
#2 0x7ac3c0 in opj_dwt_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/dwt.c:475:9
#3 0x81c4d7 in opj_tcd_dwt_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/tcd.c:1629:31
#4 0x81bf3b in opj_tcd_decode_tile /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/tcd.c:1318:20
#5 0x7c8e47 in opj_j2k_decode_tile /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/j2k.c:7914:15
#6 0x7de2f7 in opj_j2k_decode_tiles /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/j2k.c:9428:23
#7 0x7c4df7 in opj_j2k_exec /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/j2k.c:7292:41
#8 0x7ce8e3 in opj_j2k_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/j2k.c:9619:15
#9 0x7e5adf in opj_jp2_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/jp2.c:1406:8
#10 0x7f2133 in opj_decode /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/openjpeg.c:412:10
#11 0x831d9 in main /Users/Matt/Dev/OpenJpeg/issue/src/bin/jp2/opj_decompress.c:1269:10
#12 0x912416d8 in start (/usr/lib/system/libdyld.dylib+0x36d8)
#13 0x4 (<unknown module>)
SUMMARY: AddressSanitizer: heap-buffer-overflow /Users/Matt/Dev/OpenJpeg/issue/src/lib/openjp2/dwt.c:313
opj_dwt_decode_1_
Shadow bytes around the buggy address:
0x206a0610: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x206a0620: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x206a0630: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x206a0640: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x206a0650: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x206a0660: fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]00 00
0x206a0670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x206a0680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x206a0690: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x206a06a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x206a06b0: 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
ASan internal: fe
==9834==ABORTING
Reported by mayeut on 2014-12-17 21:52:09
@antonin,
This is the same issue as Issue 394
jpylyzer returns with <quantizationConsistentWithLevels>False</quantizationConsistentWithLevels>
in both cases.
For the other image, still on trunk, ASan build :
./bin/opj_decompress -i ../../data/input/nonregression/v4dwt_interleave_h.gsr105.j2k
-o 0.bmp
[INFO] Start to read j2k main header (0).
[INFO] Main header has been correctly decoded.
[INFO] No decoded area parameters, set the decoded area to the whole image
[INFO] Header of tile 1 / 1 has been read.
[INFO] Tile 1/1 has been decoded.
[INFO] Image data has been updated with tile 1.
BMP CONVERSION: Truncating component 0 from 16 bits to 8 bits
[INFO] Generated Outfile 0.bmp
No error here. Need to investigate some more.
Reported by mayeut on 2014-12-17 21:55:31
@matthieu: I'm investigating this and my feeling currently is that the segfault is due
to the huge amount of decomposition levels (32) rather than the inconsistency of the
qcd/qcc values (idem in issue 394 btw). I keep you posted.
Reported by detonin on 2015-01-07 22:05:13
@antonin,
Maybe this is related to what I saw in Issue 215.
Reported by mayeut on 2015-01-07 23:29:58
Part of the problem comes from this :
https://code.google.com/p/openjpeg/source/browse/branches/openjpeg-1.5/libopenjpeg/tcd.c#731
The amount of resolution levels leads to negative coordinate value for x1 and y1.
More specifically it comes from the int_ceildivpow2 implementation in OPJ 1.X (this
has been fixed in 2.X). It should use long int and not int.
Reported by detonin on 2015-01-07 23:31:52
This issue was updated by revision r2990.
Reported by detonin on 2015-01-08 23:18:56
@jose: seems the segfault came from a bug in a math function implementation (int_ceildivpow2).
It had already been fixed in trunk but not yet backported in 1.5. I now patched the
branch and it does not segfault anymore on my mac. As we still have a similar non-resolved
issue in trunk, there might be other hidden bugs here. Could you confirm the bug has
been fixed on your side with the updated branch ?
Reported by detonin on 2015-01-08 23:20:26
Verified. The heap overflows in dwt_interleave_h and v4dwt_interleave_h seem fixed.
However there's a out-of-bounds read as you posted in #6, which I don't know if it
was already there or is a side effect of the fix.
Reported by jduart@google.com
on 2015-01-09 13:27:11
@jose: the out-of-bounds read is not a side effect of the fix. It has been identified
on trunk and not on 1.5 branch. Do you reproduce this with the 1.5.2 version you're
using ?
@matthieu: could you do test the PoC in branch 1.5 with asan ?
Reported by detonin on 2015-01-10 22:57:08
@antonin: yes I can see exactly the same ASAN log that was posted in #6.
Reported by jduart@google.com
on 2015-01-12 09:57:34
The file that doesn't fail under ASan still behaves badly. c.f. test result under valgrind: http://my.cdash.org/viewDynamicAnalysisFile.php?id=3174329
Fixed on master branch by commit 38770403d49528936fae44de5fc6089f0bf0c3e9
Originally reported on Google Code with ID 388
Reported by detonin on 2014-09-15 12:45:50