caffe2ncnn-poc / README.md
Ano1X8's picture
Upload 9 files
2937032 verified
|
Raw
History Blame Contribute Delete
3.91 kB
metadata
license: other
tags:
  - security
  - security-research
  - vulnerability-poc
  - caffe
  - ncnn
  - do-not-load
viewer: false

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 / .caffemodel files 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. A Deconvolution layer with kernel_w: 0, kernel_h: 1 makes maxk = kernel_w * kernel_h = 0; the next line divides weight_blob.data_size() by maxk β†’ integer divide-by-zero.
  • V2 β€” CWE-129 / CWE-125 out-of-range blobs(0) (SEGV) at caffe2ncnn.cpp:459. A Deconvolution layer whose .caffemodel entry has zero blobs makes blobs(0) a RepeatedPtrField::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. A BatchNorm layer with 3 blobs where the 3rd (scale) blob has empty data passes the blobs_size() < 3 guard but makes blobs(2).data().data()[0] dereference protobuf's null default pointer at address 0x0.

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).