--- license: unknown tags: - security - poc - huntr --- # Caffe `.prototxt` Python layer → RCE PoC `malicious_deploy.prototxt` declares a layer with `type: "Python"` and `python_param { module: "evil_layer" layer: "Pwn" }`. `GetPythonLayer()` (`src/caffe/layer_factory.cpp:290-301`) — called from `LayerRegistry::CreateLayer()` whenever `caffe.Net(prototxt, weights, phase)` loads a `.prototxt` — takes those two strings straight from the attacker's `.prototxt` with zero validation: ```cpp bp::object module = bp::import(param.python_param().module().c_str()); bp::object layer = module.attr(param.python_param().layer().c_str())(param); ``` `bp::import(module)` imports an arbitrary Python module by name (running its top-level code immediately), then instantiates an arbitrary class from it by name. `evil_layer.py` (also in this repo) is the companion module that must be importable (on `PYTHONPATH`/cwd) when the victim loads this `.prototxt` — exactly the normal distribution pattern for Caffe models that ship custom Python layers (e.g. py-faster-rcnn's `rpn/proposal_layer.py`). `BUILD_python_layer` is CMake's **default-ON** build option (`CMakeLists.txt:38`). Loading this `.prototxt` with `caffe.Net()` executes `evil_layer.py`'s module-level code and the `Pwn` class constructor. Verified against the real compiled `libcaffe.so` inside Docker (`bvlc/caffe:cpu`, `WITH_PYTHON_LAYER` confirmed) — real `caffe.Net()` call, not a source reimplementation. Reported to huntr.com as a Model File Vulnerability (MFV) submission ("Caffe" format).