Jul 3, 2023
CVE-2023-31990
Huascar Tejeda of Pentraze Cybersecurity
A NULL pointer dereference vulnerability in the OpenCV function cv::dnn::dnn4_v20221220::RemoveIdentityOps
. This vulnerability occurs when processing a malformed TensorFlow model, leading to a segmentation fault.
9.0 (Critical) - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H
The vulnerability is triggered when accessing the input of a layer in a malformed TensorFlow model, leading to a segmentation fault (SIGSEGV) at address 0x000000000008
, which points to zero page. The crash occurs specifically in the RemoveIdentityOps
function at tf_graph_simplifier.cpp:818
, when the code attempts to access the layer.input(0)
, which internally uses the google::protobuf::RepeatedPtrField::Get
method, resulting in an invalid read operation that causes the program to crash.
The RemoveIdentityOps
function iterates through the layers and checks those of type Identity
. If the input of the identity layer is not properly defined, a null pointer dereference occurs.
==1426052==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x7ffff759d8cb bp 0x7fffffffaff0 sp 0x7fffffffabc0 T0)
==1426052==The signal is caused by a READ memory access.
==1426052==Hint: address points to the zero page.
#0 0x7ffff759d8cb in cv::dnn::dnn4_v20221220::RemoveIdentityOps(opencv_tensorflow::GraphDef&) /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp
#1 0x7ffff75c6e7a in cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter::populateNet() /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_importer.cpp:3036:9
#2 0x7ffff76dcf16 in cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter::TFImporter(cv::dnn::dnn4_v20221220::Net&, char const*, unsigned long, char const*, unsigned long) /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_importer.cpp:2753:5
#3 0x7ffff76dcf16 in cv::dnn::dnn4_v20221220::Net cv::dnn::dnn4_v20221220::detail::readNet<cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter, char const*&, unsigned long&, char const*&, unsigned long&>(char const*&, unsigned long&, char const*&, unsigned long&) /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/../dnn_common.hpp:76:14
#4 0x7ffff76db002 in cv::dnn::dnn4_v20221220::Net cv::dnn::dnn4_v20221220::detail::readNetDiagnostic<cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter, char const*&, unsigned long&, char const*&, unsigned long&>(char const*&, unsigned long&, char const*&, unsigned long&) /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/../dnn_common.hpp:83:25
#5 0x7ffff76db002 in cv::dnn::dnn4_v20221220::readNetFromTensorflow(char const*, unsigned long, char const*, unsigned long) /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_importer.cpp:3248:12
#6 0x306a13 in main /home/htejeda/opencv-4.7.0/build/fuzzer.cc:43:5
#7 0x7fffe8c29d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#8 0x7fffe8c29e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#9 0x2543e4 in _start (/home/htejeda/opencv-4.7.0/build/fuzzer+0x2543e4)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp in cv::dnn::dnn4_v20221220::RemoveIdentityOps(opencv_tensorflow::GraphDef&)
==1426052==ABORTING
CRASH detected in cv::dnn::dnn4_v20221220::RemoveIdentityOps due to a fault at or near 0x0000000000000008 leading to SIGSEGV (si_signo=11) / SEGV_MAPERR (si_code=1)
Crashing thread backtrace:
#0 0x00007ffff79fdf26 in cv::dnn::dnn4_v20221220::RemoveIdentityOps (/home/htejeda/opencv-4.7.0/build/lib/libopencv_dnn.so.407)
803: void cv::dnn::dnn4_v20221220::RemoveIdentityOps(net = (opencv_tensorflow::GraphDef &)@0x7fffffffd890) {
|||:
|||: /* Local reference: cv::String type = <incomplete type>; */
|||: /* Local reference: std::vector<int, std::allocator<int> > identity_ops_idx = std::vector of length 1, capacity 1 = {4}; */
|||: /* Local reference: int li = 4; */
|||: /* Local reference: IdentityOpsMap identity_ops = std::map with 0 elements; */
|||: /* Local reference: const opencv_tensorflow::NodeDef & layer = @0x610000000840; */
816: if (type == "Identity" || type == "Dropout" || type == "PlaceholderWithDefault") {
817: identity_ops_idx.push_back(li);
818: identity_ops[layer.name()] = layer.input(0);
|||:
---: }
at /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp:818
#1 0x00007ffff7a14acf in cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter::populateNet (/home/htejeda/opencv-4.7.0/build/lib/libopencv_dnn.so.407)
3000: void cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter::populateNet(this = (cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter *)0x7fffffffd840) {
||||:
3034: CV_LOG_DEBUG(NULL, "DNN/TF: removePhaseSwitches(model) => " << netBin.node_size() << " nodes");
3035:
3036: RemoveIdentityOps(netBin);
||||:
----: }
at /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_importer.cpp:3036
#2 0x00007ffff7a664a0 in cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter::TFImporter (/home/htejeda/opencv-4.7.0/build/lib/libopencv_dnn.so.407)
????: void cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter::TFImporter(this = (cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter *)0x7fffffffd840, net = (cv::dnn::dnn4_v20221220::Net &)@0x7fffffffdc48, dataModel = (const char *)0xe2e2c0 <__fuzz_alt> "\n\005\022\001R\b\037=%\b\001\022\262l\370'\n\n\"\nx\t\177\001\"\353\021\262p\v\b\200\377\377", lenModel = (size_t)<optimized out>, dataConfig = (const char *)0x0, lenConfig = (size_t)0) {
||||:
||||: /* Local reference: const char * dataConfig = 0x0; */
||||: /* Local reference: size_t lenConfig = 0; */
2751: ReadTFNetParamsFromTextBufferOrDie(dataConfig, lenConfig, &netTxt);
2752: }
2753: populateNet();
||||:
----: }
at /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_importer.cpp:2753
#3 0x00007ffff7a664a0 in cv::dnn::dnn4_v20221220::detail::readNet<cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter, char const*&, unsigned long&, char const*&, unsigned long&> (/home/htejeda/opencv-4.7.0/build/lib/libopencv_dnn.so.407)
73: cv::dnn::dnn4_v20221220::Net cv::dnn::dnn4_v20221220::detail::readNet<cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter, char const*&, unsigned long&, char const*&, unsigned long&>(args = (const char *&)<optimized out>, args = (unsigned long &)<optimized out>, args = (const char *&)<optimized out>, args = (unsigned long &)<optimized out>) {
||: /* Local reference: cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter importer = {fp_denormals_ignore_scope = {saved_state = {reserved = {32832, 0, 5263472, 0, 4294958304, 32767, 4294958208, 32767, 4294958336, 3... */
||: /* Local reference: unsigned long & args = <optimized out>; */
74: {
75: Net net;
76: Importer importer(net, std::forward<Args>(args)...);
||:
--: }
at /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/../dnn_common.hpp:76
#4 0x00007ffff7a0eb5d in cv::dnn::dnn4_v20221220::detail::readNetDiagnostic<cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter, char const*&, unsigned long&, char const*&, unsigned long&> (/home/htejeda/opencv-4.7.0/build/lib/libopencv_dnn.so.407)
??: cv::dnn::dnn4_v20221220::Net cv::dnn::dnn4_v20221220::detail::readNetDiagnostic<cv::dnn::dnn4_v20221220::(anonymous namespace)::TFImporter, char const*&, unsigned long&, char const*&, unsigned long&>(args = (const char *&)@0x7fffffffdc40, args = (unsigned long &)@0x7fffffffdc38, args = (const char *&)@0x7fffffffdc30, args = (unsigned long &)@0x7fffffffdc28) {
||:
||: /* Local reference: unsigned long & args = @0x7fffffffdc28; */
||: /* Local reference: cv::dnn::dnn4_v20221220::Net maybeDebugNet = {impl = {<std::shared_ptr<cv::dnn::dnn4_v20221220::Net::Impl>> = std::shared_ptr<cv::dnn::dnn4_v20221220::Net::Impl> (use count 1, weak count 0) = {get() =... */
81: Net readNetDiagnostic(Args&& ... args)
82: {
83: Net maybeDebugNet = readNet<Importer>(std::forward<Args>(args)...);
||:
--: }
at /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/../dnn_common.hpp:83
#5 0x00007ffff7a0eb5d in cv::dnn::dnn4_v20221220::readNetFromTensorflow (/home/htejeda/opencv-4.7.0/build/lib/libopencv_dnn.so.407)
3245: cv::dnn::dnn4_v20221220::Net cv::dnn::dnn4_v20221220::readNetFromTensorflow(bufferModel = (const char *)0xe2e2c0 <__fuzz_alt> "\n\005\022\001R\b\037=%\b\001\022\262l\370'\n\n\"\nx\t\177\001\"\353\021\262p\v\b\200\377\377", lenModel = (size_t)9712, bufferConfig = (const char *)0x0, lenConfig = (size_t)0) {
||||: /* Local reference: const char * bufferConfig = 0x0; */
||||: /* Local reference: size_t lenConfig = 0; */
||||: /* Local reference: const char * bufferModel = 0xe2e2c0 <__fuzz_alt> "\n\005\022\001R\b\037=%\b\001\022\262l\370'\n\n\"\nx\t\177\001\"\353\021\262p\v\b\200\377\377"; */
||||: /* Local reference: size_t lenModel = 9712; */
3246: const char* bufferConfig, size_t lenConfig)
3247: {
3248: return detail::readNetDiagnostic<TFImporter>(bufferModel, lenModel, bufferConfig, lenConfig);
||||:
----: }
at /home/htejeda/opencv-4.7.0/modules/dnn/src/tensorflow/tf_importer.cpp:3248
#6 0x00000000004cf24c in main (/home/htejeda/opencv-4.7.0-asan/build/fuzzer)
30: int main(argc = (int)1, argv = (char **)0x7fffffffdfb8) {
||:
||: /* Local reference: unsigned char * data = 0xe2e2c0 <__fuzz_alt> "\n\005\022\001R\b\037=%\b\001\022\262l\370'\n\n\"\nx\t\177\001\"\353\021\262p\v\b\200\377\377"; */
||: /* Local reference: size_t size = 9712; */
41:
42: try {
43: readNetFromTensorflow((const char*)data, size);
||:
--: }
at fuzzer.cc:43
Crash context:
/* Register reference: rbp - 0x0000602000005d50 (0x602000005d50) */
/* Register reference: rax - 0x0000000000000000 (0) */
Execution stopped here ==> 0x00007ffff79fdf26: mov rbp,QWORD PTR [rax+0x8]
Register info:
rax - 0x0000000000000000 (0)
rbx - 0x0000000000000000 (0)
rcx - 0x0000610000000840 (106652627896384)
rdx - 0x0000000000000001 (1)
rsi - 0x000060300001f3c0 (105759274824640)
rdi - 0x0000602000005d50 (105690555243856)
rbp - 0x0000602000005d50 (0x602000005d50)
rsp - 0x00007fffffffd420 (0x7fffffffd420)
r8 - 0x00007ffff6fa8000 (140737336999936)
r9 - 0x0000000000000000 (0)
r10 - 0x0000000000000002 (2)
r11 - 0x0000000000000010 (16)
r12 - 0x0000602000005d50 (105690555243856)
r13 - 0x0000000000000001 (1)
r14 - 0x0000000000000004 (4)
r15 - 0x0000000000507ee0 (5275360)
rip - 0x00007ffff79fdf26 (0x7ffff79fdf26 <cv::dnn::dnn4_v20221220::RemoveIdentityOps(opencv_tensorflow::GraphDef&)+1286>)
eflags - 0x00010202 ([ IF RF ])
cs - 0x00000033 (51)
ss - 0x0000002b (43)
ds - 0x00000000 (0)
es - 0x00000000 (0)
fs - 0x00000000 (0)
gs - 0x00000000 (0)
Evaluación proactiva utilizando tácticas, técnicas y procedimientos de atacantes reales para identificar fallas de seguridad, configuraciones incorrectas y vulnerabilidades.
Protección integral de aplicaciones, garantizando la seguridad en todas las fases del desarrollo.
Simulación avanzada de ataques cibernéticos para evaluar y mejorar la capacidad de respuesta de una organización.
Proceso proactivo para identificar, priorizar y abordar las vulnerabilidades de seguridad en sistemas y software, mejorando la defensa de una organización contra las amenazas cibernéticas en evolución.