# ZBar Stack-based Buffer Overflow Vulnerability ### CVE Number CVE-2023-40890 ### Summary A stack-based buffer overflow vulnerability exists in the *lookup_sequence* function of ZBar 0.23.90. Specially crafted QR codes may lead to information disclosure and/or arbitrary code execution. To trigger this vulnerability, an attacker can digitally input the malicious QR code, or prepare it to be physically scanned by the vulnerable scanner. ### Tested Versions ZBar 0.23.90 ### Product URLs https://github.com/mchehab/zbar/releases/tag/0.23.90 <!-- ### Details --> <!-- When reading in an `.stl` file with the `--export-gcode` argument, `class PerimeterGenerator` is invoked. The class has some pointers to objects, but it does not provide a destructor and instead uses the default destructor. However, the default destructor only destroys the pointer, but not what the pointer was pointing to. Therefore, the allocated memories are not properly released upon the destruction of `class PerimeterGenerator`, leading to potential memory exhaustion. ```cpp=38 class PerimeterGenerator { public: // Inputs: const SurfaceCollection* slices; const ExPolygonCollection* lower_slices; double layer_height; int layer_id; Flow perimeter_flow; Flow ext_perimeter_flow; Flow overhang_flow; Flow solid_infill_flow; PrintRegionConfig* config; PrintObjectConfig* object_config; PrintConfig* print_config; // Outputs: ExtrusionEntityCollection* loops; ExtrusionEntityCollection* gap_fill; SurfaceCollection* fill_surfaces; PerimeterGenerator( // Input: const SurfaceCollection* slices, double layer_height, Flow flow, PrintRegionConfig* config, PrintObjectConfig* object_config, PrintConfig* print_config, // Output: // Loops with the external thin walls ExtrusionEntityCollection* loops, // Gaps without the thin walls ExtrusionEntityCollection* gap_fill, // Infills without the gap fills SurfaceCollection* fill_surfaces) : slices(slices), lower_slices(NULL), layer_height(layer_height), layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow), overhang_flow(flow), solid_infill_flow(flow), config(config), object_config(object_config), print_config(print_config), loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces), _ext_mm3_per_mm(-1), _mm3_per_mm(-1), _mm3_per_mm_overhang(-1) {}; void process(); private: double _ext_mm3_per_mm; double _mm3_per_mm; double _mm3_per_mm_overhang; Polygons _lower_slices_p; ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const; ExtrusionEntityCollection _variable_width (const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const; }; } ``` --> ### Crash Information ```sh ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe8c2052b8 at pc 0x7fd25c0d6ba3 bp 0x7ffe8c205130 sp 0x7ffe8c205128 WRITE of size 4 at 0x7ffe8c2052b8 thread T0 #0 0x7fd25c0d6ba2 in lookup_sequence /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/decoder/databar.c:703:12 #1 0x7fd25c0d6ba2 in match_segment_exp /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/decoder/databar.c:763 #2 0x7fd25c0d6ba2 in decode_char /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/decoder/databar.c:1086 #3 0x7fd25c0cda9b in decode_finder /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/decoder/databar.c:1222:14 #4 0x7fd25c0cda9b in _zbar_decode_databar /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/decoder/databar.c:1242 #5 0x7fd25c0c5c52 in zbar_decode_width /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/decoder.c:270:15 #6 0x7fd25c0c378a in process_edge /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/scanner.c:173:16 #7 0x7fd25c0c378a in zbar_scan_y /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/scanner.c:261 #8 0x7fd25c0c0a6f in zbar_scan_image /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/img_scanner.c:773:17 #9 0x5503cb in zbar::ImageScanner::scan(zbar::Image&) /usr/local/include/zbar/ImageScanner.h:113:16 #10 0x5503cb in LLVMFuzzerTestOneInput /home/fuzzer/ramdisk_fuzz/libfuzz/src/fuzz.cpp:98 #11 0x42fb77 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/fuzzer/ramdisk_fuzz/libfuzz/fuzzer+0x42fb77) #12 0x43a3e4 in fuzzer::Fuzzer::MutateAndTestOne() (/home/fuzzer/ramdisk_fuzz/libfuzz/fuzzer+0x43a3e4) #13 0x43ba4f in fuzzer::Fuzzer::Loop(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fuzzer::fuzzer_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) (/home/fuzzer/ramdisk_fuzz/libfuzz/fuzzer+0x43ba4f) #14 0x42ae0c in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/fuzzer/ramdisk_fuzz/libfuzz/fuzzer+0x42ae0c) #15 0x41dc82 in main (/home/fuzzer/ramdisk_fuzz/libfuzz/fuzzer+0x41dc82) #16 0x7fd257e53bf6 in __libc_start_main /build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c:310 #17 0x41dd49 in _start (/home/fuzzer/ramdisk_fuzz/libfuzz/fuzzer+0x41dd49) Address 0x7ffe8c2052b8 is located in stack of thread T0 at offset 376 in frame #0 0x7fd25c0ce46f in decode_char /home/fuzzer/ramdisk_fuzz/ZBar_backup/zbar/decoder/databar.c:955 This frame has 6 object(s): [32, 120) 'bestsegs.i' (line 716) [160, 248) 'segs.i333' (line 716) [288, 376) 'seq.i' (line 716) <== Memory access at offset 376 overflows this variable [416, 544) 'iseg.i' (line 718) [576, 592) 'd.i' (line 645) [608, 616) 'emin' (line 958) ``` ### POC https://hackmd.io/_uploads/SJAt34YUa.png ![stack-fcc7c2c53866feaf57855438616587721a1274b6](https://hackmd.io/_uploads/SJAt34YUa.png)