opencv/opencv

OpenEXR vulnerabilities

wqh17101 opened this issue ยท 21 comments

OpenCV 4.5.5/3.4.17: disabled OpenEXR in runtime: #21327


System information (version)
  • OpenCV => 4.5.2
  • Operating System / Platform => Linux
  • Compiler => gcc 7.3.0
Detailed description

For openexr
according to http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=openexr

CVE-2021-23169
CVE-2021-3479
CVE-2020-15306
CVE-2020-15304
CVE-2020-11758
CVE-2021-3605
CVE-2021-23215
CVE-2020-15305
CVE-2020-11760
CVE-2020-11765

For openjpeg
according to http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-29338

 CVE-2021-29338
Steps to reproduce

build for default

Issue submission checklist
  • I report the issue, it's not a question
  • I checked the problem with documentation, FAQ, open issues,
    forum.opencv.org, Stack Overflow, etc and have not found solution
  • I updated to latest OpenCV version and the issue is still there
  • There is reproducer code and related data files: videos, images, onnx, etc

Why is it so hard to put text information as text? Text screenshots are ridiculous.
Do you understand that this blocks searching?

Why is it so hard to put text information as text? Text screenshots are ridiculous. Do you understand that this blocks searching?

Sorry for that.
according to http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=openexr

CVE-2021-23169
CVE-2021-3479
CVE-2020-15306
CVE-2020-15304
CVE-2020-11758
CVE-2021-3605
CVE-2021-23215
CVE-2020-15305
CVE-2020-11760
CVE-2020-11765

Thank you! Updated the initial post.

Also openjpeg v2.4.0 you bundled has a Vulnerability which is CVE-2021-29338.
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-29338 @alalek

CVE-2021-29338
This occurs when the attacker uses the command line option "-ImgDir" on a directory that contains 1048576 files.

Probably not applicable to OpenCV. We don't use OpenJPEG tools or apps. OpenCV uses decoder/encoder API subset only.

Also there are no new releases yet: https://github.com/uclouvain/openjpeg/releases

CVE-2021-29338
This occurs when the attacker uses the command line option "-ImgDir" on a directory that contains 1048576 files.

Probably not applicable to OpenCV. We don't use OpenJPEG tools or apps. OpenCV uses decoder/encoder API subset only.

Also there are no new releases yet: https://github.com/uclouvain/openjpeg/releases

I think so. You'd better have an eye on it.

I have prepared PR #21327 which disables bundled-in OpenEXR in runtime with link on this issue. So lets keep OpenEXR only problems in this issue.

If you have concerns about openjpeg please open another new issue. Initial analyzing shows that OpenCV is not affected by OpenJPEG issue, see the comment above. More analyzing requires more input/details (which we don't have).

to fix openexr maybe you can update it to 3.x

New OpenEXR requires C++11, OpenCV 3.4 is C++98. So no upgrade is planned here.
OpenEXR upgrade PR for OpenCV 4.x is here: #21324 (to be discussed after NY holidays).

Hi,
I ran into this issue:
image

Hence I wanted to bump this issue and ask if there's any solution (like downgrading openCV to solve this issue in the meantime)

If you still need OpenEXR functionality and ensure that provided inputs are valid (from trusted sources) then you may turn off mentioned flag through environment variables (check internet how to use them).

Any downgrading attempt is a security hole. Not recommended in general.


Avoid posting text information through screenshots in internet. It is ridiculous.

@alalek Wouldn't merging #21324 help fix the security issues?

@alalek Hi. I'm having a same problem as fschiffers, currently using opencv 4.5.5. I'd be really grateful if you tell me more specific ways how to fix this problem using environment variables. I've tried following instructions from the error message which was using export OPENCV_IO_ENABLE_OPENEXR = true or alternatively by os.environ ~ = 'true' but didn't work. Thanks

@skt0725

Both

OPENCV_IO_ENABLE_OPENEXR=1 python my_script.py

Or using os before importing cv2 works

os.environ["OPENCV_IO_ENABLE_OPENEXR"]="1"

Why do you think you have the right to disable EXR without thinking how many applications will stop because of this decision.
at least give us the choice , or make another option to enable it (easily not by unclear environement flag)

cr333 commented

Or using os before importing cv2 works

os.environ["OPENCV_IO_ENABLE_OPENEXR"]="1"

FYI, this environment variable can also be defined after importing cv2, as it is only checked when opening the first EXR image for reading/writing (see source).

We recently noticed this issue as well. Evaluating OpenCV's alternatives to save/load of floating point images shows that TIFF and HDR formats work, but are not lossless (at least for floats). PFM works, but the image files are about 4-5 times as large as using OpenEXR. Therefore, we would like to keep using OpenEXR.

The first solution is to always define environment variables on each machine that should use it. This is the same as always activating OpenEXR by replacing the function isOpenEXREnabled() inside grfmt_exr.cpp with

static bool isOpenEXREnabled()
{
   return true;
}

which avoids using environment variables but is unsafe for exactly the same reasoning.

To our understanding from the discussion here and the linked issues, the reason is not a general security risk but only an outdated OpenEXR version used inside OpenCV. Upgrading to a more recent one would be a solution, but is not intended because OpenEXR became a rather large library so far. Therefore, explicitly compiling OpenEXR and adding it as a dependency to OpenCV is the way to go.

Here, we tried to compile OpenEXR as static library using VS2022 and added it to OpenCV using the OpenEXR_DIR and Imath_DIR CMake options. Compiling works expect that there is an additional but unnecessary dependency to zlib_static.lib in opencv_imgcodecs - the linker prints an error that this is missing while manually removing it from the project file (after it was generated by CMake) works fine. Presumably, this has to be fixed inside OpenEXR's CMake scripts (similar issue)

Thereafter, compiling works except that isOpenEXREnabled() should be extended such that the default return depends on the OpenEXR version. Is our understanding correct or are there different recommendations to solve this issue?

edit:
After analyzing the integration of OpenEXR in more detail, there is already an extended compile-time option available inside modules\imgcodecs\CMakeLists.txt. There already is a preprocessor definition OPENCV_IMGCODECS_USE_OPENEXR (not to be confused with the OPENCV_IO_ENABLE_OPENEXR environment variable checked at runtime) that is enabled if an external OpenEXR version is used. However, currently there seems to be an error in the OpenEXRTargets.cmake script that results in a link error (missing zlib_static.lib) such that this option requires manually fixing the error in the project files.

Besides this, the preprocessor definition OPENCV_IMGCODECS_USE_OPENEXR can alternatively be set by defining the CMake variable OPENCV_IO_FORCE_OPENEXR=True. This results in always activating OpenEXR at runtime as long as it is not explicitly deactivated by setting the environment variable OPENCV_IO_ENABLE_OPENEXR = 0. For the moment, this solution seems to be more convenient than explicitly activating OpenEXR whenever needed.

A couple years back in this thread, needing C++98 compatibility was cited as the reason for not upgrading to the newer OpenEXR in which all these CVEs have been fixed.

Since then, OpenEXR has acquired a core C API as well. This should allow re-inclusion.

I dont think this issue is fully resolved yet. Despite providing the environment variable,

os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1"

It is still failing, is there anything else we need to do, perhaps manually compile opencv with some flags?

Python 3.7.17 (default, Nov 24 2023, 18:52:28) 
[GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.

import os
os.environ["OPENCV_IO_ENABLE_OPENEXR"]="1"
import cv2
cv2.__version__
'4.8.1'
img = cv2.imread('/path/to/exr/file')
[ WARN:0@423.487] global grfmt_exr.cpp:102 initOpenEXR imgcodecs: OpenEXR codec is disabled. You can enable it via 'OPENCV_IO_ENABLE_OPENEXR' option. Refer for details and cautions here: https://github.com/opencv/opencv/issues/21326
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
cv2.error: OpenCV(4.8.1) /io/opencv/modules/imgcodecs/src/grfmt_exr.cpp:103: error: (-213:The function/feature is not implemented) imgcodecs: OpenEXR codec is disabled. You can enable it via 'OPENCV_IO_ENABLE_OPENEXR' option. Refer for details and cautions here: https://github.com/opencv/opencv/issues/21326 in function 'initOpenEXR'
cr333 commented

Your code works fine for me in a fresh shell (Python 3.8.13, OpenCV 4.6.0, Ubuntu).

Not sure why it fails for you. Maybe there's an issue with updating the environment variable?

If you are open to recompiling OpenCV, it looks like enabling the CMake option OPENCV_IO_FORCE_OPENEXR compiles OpenCV with the OPENCV_IMGCODECS_USE_OPENEXR flag that should make the environment variable unnecessary. Hope this helps.

OPENCV_IMGCODECS_USE_OPENEXR flag should really be enabled by default