Skip to content

Heap buffer overlfow in opj_j2k_read_sod #1620

@soiax

Description

@soiax

Hi,

The vulnerability stems from a mismatch between:

  1. The tp_index array size, which is allocated based on TLM (Tile Length Marker) entries
  2. The current_tpsno value, which is set from SOT (Start Of Tile-part) marker's TPsot field

When a maliciously crafted file provides inconsistent TLM and SOT data, the decoder can write beyond the allocated tp_index buffer.

In opj_j2k_read_sod() (lines 5083-5090), the current_tpsno value is used to index tp_index without any bounds check:


// Lines 5083-5090: VULNERABLE - No bounds check before array access
OPJ_UINT32 l_current_tile_part =
    l_cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno;
l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_header
    =
        l_current_pos;
l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_pos
    =
        l_current_pos + p_j2k->m_specific_param.m_decoder.m_sot_length + 2;

Similar bug was fixed in https://github.com/uclouvain/openjpeg/pull/1565/files with a bounds check:

     if (cstr_index->tile_index[tileno].tp_index &&
                l_current_tile_part < cstr_index->tile_index[tileno].nb_tps) {

ASAN log of ./opj_decompress:


==967857==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000000030 at pc 0x000000542219 bp 0x7ffebf1782a0 sp 0x7ffebf178298
WRITE of size 8 at 0x603000000030 thread T0
    #0 0x542218 in opj_j2k_read_sod /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:5124:13
    #1 0x53cf57 in opj_j2k_read_tile_header /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:9956:19
    #2 0x57e82f in opj_j2k_decode_tiles /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:12123:19
    #3 0x5392cf in opj_j2k_exec /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:9225:33
    #4 0x5506b5 in opj_j2k_decode /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:12470:11
    #5 0x51ebf7 in opj_decode /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/openjpeg.c:526:16
    #6 0x4cca42 in main /mnt/f/fuzz/openjpeg-master/src/bin/jp2/opj_decompress.c:1582:19
    #7 0x7c5f6f757082 in __libc_start_main /build/glibc-B3wQXB/glibc-2.31/csu/../csu/libc-start.c:308:16
    #8 0x41c43d in _start (/mnt/f/fuzz/openjpeg-master/opj_decompress_asan+0x41c43d)

0x603000000030 is located 8 bytes to the right of 24-byte region [0x603000000010,0x603000000028)
allocated by thread T0 here:
    #0 0x496622 in calloc (/mnt/f/fuzz/openjpeg-master/opj_decompress_asan+0x496622)
    #1 0x521936 in opj_calloc /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/opj_malloc.c:208:11
    #2 0x55fcb2 in opj_j2k_build_tp_index_from_tlm /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:8983:57
    #3 0x55ad7c in opj_j2k_read_header_procedure /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:9196:5
    #4 0x5392cf in opj_j2k_exec /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:9225:33
    #5 0x538e1c in opj_j2k_read_header /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:8570:11
    #6 0x51e90c in opj_read_header /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/openjpeg.c:475:16
    #7 0x4cc134 in main /mnt/f/fuzz/openjpeg-master/src/bin/jp2/opj_decompress.c:1520:15
    #8 0x7c5f6f757082 in __libc_start_main /build/glibc-B3wQXB/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /mnt/f/fuzz/openjpeg-master/src/lib/openjp2/j2k.c:5124:13 in opj_j2k_read_sod
Shadow bytes around the buggy address:
  0x0c067fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c067fff8000: fa fa 00 00 00 fa[fa]fa 00 00 00 fa fa fa fa fa
  0x0c067fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8050: 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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
  Shadow gap:              cc
==967857==ABORTING

Uploaded poc is not a ZIP, just rename it to .j2k. Github doesn't allow that extension.

poc.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions