Skip to content

Instantly share code, notes, and snippets.

@superboy-zjc
Created March 19, 2025 18:36
Show Gist options
  • Select an option

  • Save superboy-zjc/a31b8ea7466f91b437598297bf5cbce8 to your computer and use it in GitHub Desktop.

Select an option

Save superboy-zjc/a31b8ea7466f91b437598297bf5cbce8 to your computer and use it in GitHub Desktop.
sverchok class pollution vulnerability leading to github token stolen

Sverchok Class Pollution Vulnerability Leading to Arbitrary Python Runtime Tampering

Summary

Sverchok is a popular Blender addon for dataflow programming. It's Set Property Mk2 node has a class pollution vulnerability that accepts arbitrary object path to propogate property value which leads to arbitrary python runtime pollution.

An sophisticated attacker can trick victims into loading their malicious model file, which allow attackers to tamper with the python runtime to achieve stealthyly dangerous consequences, such as token stealing, DoS, etc.

Root Cause

The root cause is that the Set Property Mk2 node does not validate the object path. Attacker can use dunder variables to traverse to the global varibles, other modules to pollute runtime states.

# https://github.com/nortikin/sverchok/blob/9315e9d33fa5b459734491af1f91a3320fe423c5/nodes/object_nodes/getsetprop_mk2.py#L302-L315

  def process(self):

      if len(self.inputs) == 0:
          return

      data = self.inputs[0].sv_get()
      eval_str = apply_alias(self.prop_name, nodetree=self.id_data)
      ast_path = ast.parse(eval_str)
      # Here should detect if the path is valid
      # if double underscore, such as `.__init__.#__globals__` is used, it should be rejected
      path = parse_to_path(ast_path.body[0].value)
      obj = get_object(path)

      try:
          if isinstance(obj, (int, float, str, bpy_prop_array)):

              obj = get_object(path[:-1])
              p_type, value = path[-1]
              if p_type == "attr":
                  setattr(obj, value, data[0][0])
              else: 
                  obj[value] = data[0][0]
          else:
              assign_data(obj, data)

      except Exception as err:
          print(err)

Proof of Concept

This section shows how to exploit the vulnerability to steal github token.

  • Add a Set Property Mk2 node with the object path bpy.utils.execfile.__globals__["_sys"].modules["sverchok"].utils.sv_gist_tools.API_URL, which value is the github gist url that sverchok refers to.

  • Add a Simple Text node and set the value to the attacker's http server which will overwrite the github gist's url that sverchok refers to.

alt text

  • Export to github gist, triggering the attack. The token is exfiltrating through the http request header.

alt text

Mitigation

Validate the object path in Set Property Mk2 node in the get_object function to detect and reject the dunder variables.

# https://github.com/nortikin/sverchok/blob/9315e9d33fa5b459734491af1f91a3320fe423c5/nodes/object_nodes/getsetprop_mk2.py#L68
def get_object(path):
    '''
    - access the object specified from a path generated by parse_to_path
    - this will fail if path is invalid
    '''
    curr_object = globals()[path[0][1]]
    for t, value in path[1:]:
        # Patch at here:
        if value.startswith("__") or value.endswith("__"):
            throw ValueError("Invalid path")
        if t == "attr":
            curr_object = getattr(curr_object, value)
        elif t == "key":
            curr_object = curr_object[value]
    return curr_object

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment