Le librerie Yaml python sono anche in grado di serializzare oggetti python e non solo dati grezzi:
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
Controlla come il tuple non sia un tipo di dato grezzo e quindi sia stato serializzato. E lo stesso è accaduto con il range (preso dai builtins).
safe_load() o safe_load_all() utilizzano SafeLoader e non supportano la deserializzazione degli oggetti di classe. Esempio di deserializzazione degli oggetti di classe:
import yamlfrom yaml import UnsafeLoader, FullLoader, Loaderdata =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
Il codice precedente utilizzava unsafe_load per caricare la classe python serializzata. Questo perché in versione >= 5.1, non consente di deserializzare alcuna classe python serializzata o attributo di classe, senza un Loader specificato in load() o Loader=SafeLoader.
Le vecchie versioni di pyyaml erano vulnerabili ad attacchi di deserializzazione se non specificavi il Loader quando caricavi qualcosa: yaml.load(data)
Nota che nelle versioni recenti non puoi più chiamare .load()senza un Loader e il FullLoadernon è più vulnerabile a questo attacco.
RCE
I payload personalizzati possono essere creati utilizzando moduli Python YAML come PyYAML o ruamel.yaml. Questi payload possono sfruttare vulnerabilità nei sistemi che deserializzano input non affidabili senza una corretta sanificazione.