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