TheMrEvil's picture
Remove internal duplicate-check section from card (not part of disclosure)
4fe03f5 verified
|
Raw
History Blame Contribute Delete
2.77 kB

OpenCV FileStorage decodeFormat stack buffer overflow (CWE-787) PoC

Proof of concept for a stack buffer overflow / out-of-bounds write in OpenCV's FileStorage data-type parser, triggered when a Mat is read from a crafted .json or .yml model file.

This repository is gated: the crafted files are weaponized inputs. Access is pre-granted to protectai-bot for huntr review.

What it is

modules/core/src/persistence.cpp → decodeFormat(const char* dt, int* fmt_pairs, int max_len) writes one (count, depth) int pair per type token of the dt string into fmt_pairs. It does max_len *= 2 and only stops when the index reaches 2 * 128 = 256 ints. But two callers declare the destination at the 1x size:

caller line buffer
decodeSimpleFormat() persistence.cpp:319 int fmt_pairs[CV_FS_MAX_FMT_PAIRS] (128)
calcElemSize() persistence.cpp:269 int fmt_pairs[CV_FS_MAX_FMT_PAIRS] (128)
writeRawData / readRaw / parseBase64 1140 / 1838 / 2645 [CV_FS_MAX_FMT_PAIRS * 2] (256) ✔

CV_FS_MAX_FMT_PAIRS = 128. A dt with more than 64 type pairs overflows the 128-int stack buffer by up to ~512 bytes. The overflowing values are the pair counts, parsed with strtol(dt), so they are attacker-controlled.

decodeSimpleFormat() is reached at load time from the matrix reader read(const FileNode&, Mat&) (persistence_types.cpp:130) on the file's dt field, before any validation.

Files

  • poc.json, poc.yml — 1x1 matrix node x with a 120-pair dt (each count = 0x41414141).
  • benign.json, benign.yml — same files with a normal dt; load cleanly.
  • make_poc.py — regenerates the files from a cv2-written valid skeleton.
  • verify.py — child-process differential runner.
  • asan_repro.cpp, asan_report.txt — standalone AddressSanitizer reproducer (the exact source of decodeFormat/decodeSimpleFormat) and its report, deterministically showing stack-buffer-overflow WRITE of size 4.
  • linux_verify.sh — one-shot driver.

Reproduce (Linux, pip install opencv-python ≤ 4.13.0)

python make_poc.py
python verify.py
#   benign.json  rc=0    loaded ok
#   poc.json     rc=-11  CRASH (SIGSEGV)
#   poc.yml      rc=-11  CRASH (SIGSEGV)

clang++ -O0 -g -fsanitize=address asan_repro.cpp -o asan_repro && ./asan_repro 120
#   AddressSanitizer: stack-buffer-overflow  WRITE of size 4  in decodeFormat

Impact

Reading a Mat from an untrusted FileStorage file (directly, or via the cv2.ml model loaders that persist as FileStorage) performs a controllable out-of-bounds stack write. Reliable outcome is a process crash (DoS); ceiling is memory corruption / control-flow hijack subject to stack-protector and ASLR.