YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
PoC β code execution when loading a CNTK v2 (.cntk) model
Loading an untrusted CNTK v2 model with the normal cntk.Function.load() runs code
embedded in the file. A CNTK graph can hold a Python UserFunction node, and the node
stores the function's module and class as plain strings. On load CNTK's UDF
deserializer does exec("from {module} import {class}") on those attacker-controlled
strings, so the file alone decides what gets imported and run.
model_inject_linux.cntk needs no external file: the module is byte-patched to
builtins and the class string carries a newline-injected payload, so loading it
runs os.system('id ...') and drops /tmp/PWNED_cntk.
Files
model_inject_linux.cntkβ self-contained malicious model (stdlib-only, no attacker .py).verify.pyβ loads it and prints the marker.model_evil.cntk+evil_udf.pyβ the planted-module variant (module named in the model is imported from sys.path).build_inject_linux.pyβ how the injected model was built.Dockerfileβ the exact clean-room image (python:3.6 + cntk 2.7 + OpenMPI 1.10).
Reproduce
CNTK 2.7 is py3.5/3.6 only. In the clean room I confirmed it on a stock wheel:
docker build -t cntk-poc . # python:3.6-slim + pip install cntk==2.7 + OpenMPI 1.10
docker run --rm -v "$PWD":/poc -w /poc cntk-poc python verify.py
# marker after : True
# uid=0(root) gid=0(root) groups=0(root)
# INJECTED_NO_EXTERNAL_FILE
Or on any py3.6 box: pip install cntk==2.7 then python verify.py.
Why it matters
Any service that loads a user-supplied .cntk runs attacker code as the loading process.
It is the default load path, no flag turns it off, and ModelScan does not scan .cntk
at all, so the file looks clean.