ncnn caffe2ncnn Caffe-parser crashes β security-research PoC artifacts
β οΈ SECURITY RESEARCH ARTIFACTS β DO NOT CONVERT OR LOAD THESE FILES OUTSIDE AN ISOLATED, INTENTIONAL TEST ENVIRONMENT. These
.prototxt/.caffemodelfiles are intentionally malformed to crash a model converter. They are not neural networks, contain no useful weights, and must never be fed to a production or shared conversion pipeline.
This repository hosts the malicious model artifacts for a coordinated, authorized vulnerability disclosure submitted through the huntr Model File Vulnerability (MFV) program against Tencent/ncnn.
What this is
Three deterministic crashes in tools/caffe/caffe2ncnn.cpp (the Caffe β ncnn converter) β one root class: ncnn uses file-controlled blob counts and kernel dimensions as divisors and array indices without validation:
- V1 β CWE-369 divide-by-zero (SIGFPE) at
caffe2ncnn.cpp:515. ADeconvolutionlayer withkernel_w: 0, kernel_h: 1makesmaxk = kernel_w * kernel_h = 0; the next line dividesweight_blob.data_size()bymaxkβ integer divide-by-zero. - V2 β CWE-129 / CWE-125 out-of-range
blobs(0)(SEGV) atcaffe2ncnn.cpp:459. ADeconvolutionlayer whose.caffemodelentry has zero blobs makesblobs(0)aRepeatedPtrField::Get(0)on an empty field; in a release protobuf build (DCHECK compiled out) this dereferences unmapped memory. - V3 β CWE-476 null-pointer dereference (SEGV) at
caffe2ncnn.cpp:304. ABatchNormlayer with 3 blobs where the 3rd (scale) blob has emptydatapasses theblobs_size() < 3guard but makesblobs(2).data().data()[0]dereference protobuf's null default pointer at address0x0.
Trust boundary: a developer downloads an untrusted pretrained Caffe model from a model zoo and runs caffe2ncnn model.prototxt model.caffemodel out.param out.bin. All three crashes are denial-of-service only β no controllable write, out-of-bounds read disclosure, or code execution is claimed. The same unvalidated-count class recurs in other layer branches (BatchNorm :282/:283, Convolution :344, etc.).
Files
| File | Triggers |
|---|---|
evil.prototxt + evil.caffemodel |
V1 β divide-by-zero (SIGFPE) at :515. Deconvolution kernel_w=0 β maxk=0. |
oob.prototxt + oob.caffemodel |
V2 β out-of-range blobs(0) (SEGV) at :459. Deconvolution layer with zero blobs. |
bn.prototxt + bn.caffemodel |
V3 β null-pointer deref (SEGV @ 0x0) at :304. BatchNorm with 3 blobs, empty 3rd blob. |
craft.py / craft_oob.py / craft_bn.py |
Scripts that regenerate the three model pairs from ncnn's bundled caffe.proto. |
ASAN-OUTPUT.txt / ASAN-OUTPUT-oob.txt / ASAN-OUTPUT-bn.txt |
AddressSanitizer transcripts for V1, V2, V3 (FPE at :515; SEGV in RepeatedPtrField::Get via :459; null-deref SEGV at :304). |
Reproduce (isolated environment only)
Build caffe2ncnn from ncnn @ dda2e28 (release protobuf; add -fsanitize=address -g for a deterministic signal with a source line), then:
# V1 β SIGFPE at caffe2ncnn.cpp:515
./caffe2ncnn evil.prototxt evil.caffemodel out.param out.bin
# V2 β SEGV at caffe2ncnn.cpp:459
./caffe2ncnn oob.prototxt oob.caffemodel out.param out.bin
# V3 β SEGV (null deref) at caffe2ncnn.cpp:304
./caffe2ncnn bn.prototxt bn.caffemodel out.param out.bin
See the huntr report for the full build recipe and write-up.
Responsible use
Published solely to give the huntr triage team a reproducible artifact for coordinated disclosure. Do not redeploy, repackage, or convert these files against any system you do not own and intend to test. Reporter: Ano1X8 (@ano1x8).