Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memory exhauted and hangs long time when use 64bit opj_decompress (CVE-2019-6988) #1178

Open
yanxxd opened this issue Jan 17, 2019 · 15 comments

Comments

@yanxxd
Copy link

yanxxd commented Jan 17, 2019

I found a problem which will cause memory is exhausted, and program hang for 8 minutes. My test server had 112GB of memory. This can cause denial of service.

Steps to Reproduce

  1. Download and unzip [POC.zip]
    POC.zip
  2. Run opj_decompress -i POC -o /tmp/1.png
  3. When I test it use 32bit opj_decompress with asan, the following is the output information
===========================================
The extension of this file is incorrect.
FOUND p:16. SHOULD BE .j2k or .jpc or .j2c
===========================================

[INFO] Start to read j2k main header (0).
[WARNING] Unknown marker
[WARNING] Unknown marker
[WARNING] Cannot take in charge mct data within multiple MCT records
[WARNING] Unknown marker
[ERROR] Unknown progression order in COD marker
[WARNING] Unknown marker
[WARNING] Cannot take in charge mct data within multiple MCT records
[WARNING] Unknown marker
[ERROR] Unknown progression order in COD marker
[WARNING] Unknown marker
[WARNING] Cannot take in charge mct data within multiple MCT records
[WARNING] Unknown marker
[ERROR] Unknown progression order in COD marker
[WARNING] Unknown marker
[INFO] Main header has been correctly decoded.
[INFO] No decoded area parameters, set the decoded area to the whole image
=================================================================
==26110==ERROR: AddressSanitizer: allocator is out of memory trying to allocate 0x2f4ad890 bytes
    #0 0x81083a5 in calloc /soft/clang/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:155:3
    #1 0xf7dda139 in opj_calloc ./openjpeg/src/lib/openjp2/opj_malloc.c:204:12
    #2 0xf7d7685c in opj_tcd_init_tile ./openjpeg/src/lib/openjp2/tcd.c:1111:56
    #3 0xf7d87c0f in opj_tcd_init_decode_tile ./openjpeg/src/lib/openjp2/tcd.c:1184:12
    #4 0xf793a827 in opj_j2k_decode_tiles ./openjpeg/src/lib/openjp2/j2k.c:10717:19
    #5 0xf785ba1c in opj_j2k_exec ./openjpeg/src/lib/openjp2/j2k.c:8105:33

Analysis

  1. Alloc too much big memory.
  2. Maybe too many cycles

System Configuration

  • version: git commit 51f097e
  • Environment: Ubuntu 16.04.3 TLS
  • Memery Size: 112GB
  • component: 64bit opj_decompress

These vulnerabilities have been found with a more efficient version of the AFL fuzzer.

@szukw000
Copy link
Contributor

I have a simple JPEG2000 reader. Using it I found:

NAME(/tmp/POC.j2k)
LENG(2694)

ENTER read_jp2c
[0]marker(0xff4f)
    soc len(0)
[2]marker(0xff51)
    siz len(50)
    capabilities(0)[extended: 0]
    x(0 : 2147418112) y(16 : 67108896)
    xt(0 : 377547551) yt(0 : 4194336)
    IMAGE w(2147418112) h(67108880) TILE w(377547551) h(4194336)
    nr_components(4)
      component[0] signed(0) prec(2) hsep(1) vsep(231)
      component[1] signed(1) prec(12) hsep(1) vsep(255)
      component[2] signed(0) prec(2) hsep(1) vsep(1)
      component[3] signed(0) prec(1) hsep(222) vsep(255)
[54]marker(0xffff)
test_marker: type(0xffff) prefix(0xff) suffix(0xff)
 I :MARKER 0xffff is unknown.
EXIT read_jp2c
    end - s ==> -62899
EXIT with end - s ==> 0 (DEC:0)

winfried

@yanxxd
Copy link
Author

yanxxd commented Jan 18, 2019

Should memory checks be added to the program? Otherwise the memory will be exhausted.

@szukw000
Copy link
Contributor

@yanxdd , @rouault ,

j2k.c, line 9497:
==================
    /* in the absence of JP2 boxes, consider different bit depth / sign */
    /* per component is allowed */
    l_j2k->m_cp.allow_different_bit_depth_sign = 1;


j2k.c, line 2237:
==================
            } else if (!l_cp->allow_different_bit_depth_sign
                       && (l_img_comp->prec != l_prec0 || l_img_comp->sgnd != l_sgnd0)) {
                opj_event_msg(p_manager, EVT_WARNING,
                              "Despite JP2 BPC!=255, precision and/or sgnd values for comp[%d] is different than comp[0]:\n"
                              "        [0] prec(%d) sgnd(%d) [%d] prec(%d) sgnd(%d)\n", i, l_prec0, l_sgnd0,
                              i, l_img_comp->prec, l_img_comp->sgnd);
            }


JP2 BPC!=255 : jp2->bpc gets a value in jp2.c .
Why a WARNING for allowed values?

All decompressors explicitly ask for equal values,
e.g. convertpng.c, line 321:
==================================================
        fprintf(stderr,
                "imagetopng: All components shall have the same subsampling, same bit depth, same sign.\n");
        fprintf(stderr, "\tAborting\n");


Testing dx and dy in j2k.c, I get:
===================================
[INFO] Start to read j2k main header (0).
openjpeg2-2018-12-26/src/lib/openjp2/j2k.c:2248:
        [0] prec0(2) prec(2) sgnd0(0) sgnd(0)
openjpeg2-2018-12-26/src/lib/openjp2/j2k.c:2248:
        [1] prec0(2) prec(12) sgnd0(0) sgnd(1)
openjpeg2-2018-12-26/src/lib/openjp2/j2k.c:2270:
        [1] dx0(1) dx(1) dy0(231) dy(255)
[ERROR] dy(255) != dy0(231)
[ERROR] Marker handler function failed to read the marker segment
ERROR -> opj_decompress: failed to read the header

winfried

@nluedtke
Copy link

This was assigned CVE-2019-6988.

@yanxxd yanxxd closed this as completed Apr 9, 2019
@hlef
Copy link
Contributor

hlef commented Oct 7, 2019

@yanxxd is this issue invalid, or was it fixed at some point?

If this issue is invalid, we should ask for CVE rejection.

@flobeier
Copy link

flobeier commented Feb 29, 2020

@yanxxd pinging you again, has this issue been fixed by now or was it invalid?

@yanxxd
Copy link
Author

yanxxd commented Mar 1, 2020

I tested it use the latest version, git commit 563ecfb. The program run about 10 minutes, CPU 100%, MEM 100%. The following is the output:

opj_decompress -i POC -o /tmp/1.png

===========================================
The extension of this file is incorrect.
FOUND /POC. SHOULD BE .j2k or .jpc or .j2c
===========================================

[INFO] Start to read j2k main header (0).
[WARNING] Unknown marker
[WARNING] Unknown marker
[WARNING] Cannot take in charge mct data within multiple MCT records
[WARNING] Unknown marker
[ERROR] Unknown progression order in COD marker
[WARNING] Unknown marker
[WARNING] Cannot take in charge mct data within multiple MCT records
[WARNING] Unknown marker
[ERROR] Unknown progression order in COD marker
[WARNING] Unknown marker
[WARNING] Cannot take in charge mct data within multiple MCT records
[WARNING] Unknown marker
[ERROR] Unknown progression order in COD marker
[WARNING] Unknown marker
[INFO] Main header has been correctly decoded.
[INFO] No decoded area parameters, set the decoded area to the whole image
Killed

You can reproduce it use the POC.

@flobeier
Copy link

flobeier commented Mar 1, 2020

Thanks! Perhaps this issue should be reopened then.

@rouault rouault reopened this Mar 1, 2020
@rouault rouault changed the title memory exhauted and hangs long time when use 64bit opj_decompress memory exhauted and hangs long time when use 64bit opj_decompress (CVE-2019-6988) Mar 6, 2020
@rouault
Copy link
Collaborator

rouault commented Mar 6, 2020

While for this particular file (POC), we could bail out earlier given a number of corruptions in segment markers, this wouldn't fix the underlying issue. This issue is a design one. The library pre-allocates precints and codeblocks related structures, such as tagtree, for a whole tile. In the case of POC, there are for example 37 million codeblocks for one precinct, which represents 4 GB of RAM for the codeblock working memory (and other GB for tagtree etc). Completely legit JPEG2000 images could be built with the same characteristics as those corrupted images, and with sufficient huge amount of RAM could be docoded. As fixing the design of openjpeg would be enormous work, a fix would probably to set some implementation-defined thresholds, not normally reached on "normal" images, and error out if they are reached, and let the user able to override them with some environment variable.

@yanxxd
Copy link
Author

yanxxd commented Mar 7, 2020

Setting some implementation-defined thresholds may be a viable solution.

@ckauhaus
Copy link

Any news on this?

@utkarsh2102
Copy link

Hiya!
Any ETA on this!?

@malaterre
Copy link
Collaborator

@yanxxd can you reproduce CVE-2019-6988 using opj 2.4.0 ?

@JaiKishan132
Copy link

Hi, Any update on the issue?

@kingysu
Copy link

kingysu commented Nov 2, 2023

Hi, Any update on the issue?

@yanxxd @rouault

  1. I have investigated the problem recently. I found there is commit which has "solved" the problem. The commit is: f3ee448 openjp2/j2k: Validate all SGcod/SPcod/SPcoc parameter values..

  2. After some debugging, I found the code which has "solved" the problem:
    if (l_tccp->qmfbid > 1) { opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element, Invalid transformation found\n"); return OPJ_FALSE; }

  3. l_tccp->qmfbid's value is 255 and it's greater than 1, so the function will return false. Finally, the program will exit. According the spec, l_tccp->qmfbid's valid value shoud be 0 or 1.

  4. This is the output:
    ===========================================
    The extension of this file is incorrect.
    FOUND /POC. SHOULD BE .j2k or .jpc or .j2c
    ===========================================

[INFO] Start to read j2k main header (0).
[WARNING] Unknown marker
[WARNING] Unknown marker
[WARNING] Cannot take in charge mct data within multiple MCT records
[WARNING] Unknown marker
[ERROR] Unknown progression order in COD marker
[ERROR] Error reading SPCod SPCoc element, Invalid transformation found
[ERROR] Error reading COD marker
[ERROR] Marker handler function failed to read the marker segment
ERROR -> opj_decompress: failed to read the header

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests