caffe2ncnn-poc / README.md
Ano1X8's picture
Upload 9 files
2937032 verified
|
Raw
History Blame Contribute Delete
3.91 kB
---
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](https://huntr.com) 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:
```bash
# 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).