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.
AI for Cybersecurity_ Research and Practice
Unknown
John Wiley & Sons, Inc.