AskReference
ProcessAdvanced

How does the REDUCE opcode in Python's Pickle module enable attackers to execute malicious code during model deserialization?

The REDUCE opcode makes deserialization execute a function, because during unpickling it pops a callable and its arguments from the stack and invokes the callable on those arguments. Attackers craft malicious serialized data that encodes a dangerous function, such as os.system, with a harmful argument, so the function runs automatically when the model is loaded, enabling remote code execution.

Pickle serializes objects into a stack-based binary protocol made of opcodes. During deserialization, opcodes are processed in order, pushing values onto a stack and using them in operations until a STOP opcode is reached. The REDUCE opcode is special: it pops two stack values, a function and the arguments to pass to it, and executes the function with those arguments. Because REDUCE directly causes function execution, an attacker who controls the serialized payload can encode a particular callable and parameters of their choice. The book demonstrates this by creating a Payload class whose __reduce__ method returns (os.system, ('rm -rf.',)). A malicious pickler injects an instance of this Payload into a serialized PyTorch model. When a victim later calls torch.load on that file, the deserialization process encounters the injected REDUCE opcode, invokes os.system with the argument 'rm -rf.', and the destructive command executes on the victim's machine. Thus, untrusted deserialization of Pickle-based model files becomes an entry point for attacks because loading the model can trigger arbitrary code execution through REDUCE.

Key points

  • Pickle serialization encodes objects as opcodes processed on a stack during deserialization.
  • REDUCE is an opcode that pops a callable and its arguments from the stack and then calls that callable with those arguments.
  • Attackers can craft serialized data so REDUCE invokes a dangerous function such as os.system with malicious parameters.
  • A Payload class can override __reduce__ to control what callable and arguments are created during unpickling.
  • Injecting such a payload into a serialized PyTorch model causes it to execute when the victim loads the model with torch.load.
Source:AI for Cybersecurity_ Research and Practice· Cyber-AI Supply Chain Vulnerabilities· p. 493–508
Cover of AI for Cybersecurity_ Research and Practice

AI for Cybersecurity_ Research and Practice

Unknown

John Wiley & Sons, Inc.

View this ebook