Popularnym stwierdzeniem jest aby nie używać pickle
1 na danych od użytkownika ponieważ podczas ich deserializacji może dojść do ataku object injection
i wykonania złośliwego kodu.

Ale co z innymi formatami? Czy również są niebezpieczne?
Dlaczego więc programiści decydują się na używanie właśnie tego formatu?
Za pewne jedni podniosą argument o czytelności - format ten bowiem wymusza przechowywanie danych w jednej linii co wpływa na czytelności

Pozwala to również lepiej mergować zmiany - na przykład jeśli używamy systemu kontroli wersji - takich jak GIT.
Prościej bowiem edytować kod rozbity na linie niż plik json, który może nie być sformatowany i widoczny dla użytkownika jako jeden ciąg w jednej linii.
Popatrzmy zatem na dzisiejszy przykład.
import yaml
with open("test.yaml", "r") as s:
y = yaml.load(s)
print y['imie']
Odczytujemy w nim treści pliku test.yaml
przy pomocy funkcji yaml.load
a następnie wyświetlamy imię.
Format yaml
nie jest tak prosty jak mogło by się wydawać.2

W standardowym użyciu sam rozpoznaje on typ danych który jest do niego przekazywany.
Czasami jednak chcielibyśmy mieć kontrolę nad typem przechowywanym w konfiguracji.
Stąd też tagi - czyli polecenia rozpoczynające się od wykrzyknika, dzięki którym możemy wybrać typ samodzielnie.

Tak jak tutaj - gdzie wartość 0.5
będzie traktowana jako string
a nie jako float
.
W yamlu możemy również przechowywać pliki binarne, zapisując je przy pomocy kodowania base64 oraz używając tagu !!binary
.
Niektóre parsery implementują specyficzne dla danego języka tagi.
W przypadku Pythonia możemy zdefiniować tuple
przy pomocy tagu python/tuple
.
Gdzie zatem znajduje się dzisiejszy błąd?
W standardowym parserze używanym w Pythonie możemy również skorzystać z tagu apply
3, który pozwala na wywołanie dowolnej funkcji z dowolnego modułu oraz przekazanie do nich odpowiednich parametrów.
Jest to więc równoznaczne z możliwością wykonania dowolnego kodu na atakowanym serwerze.

W naszym przypadku użyjemy funkcji os.system
do wyświetlenia zawartości bieżącego katalogu.
Teraz, zamiast imienia użytkownika widzimy treść katalogu.

Jak się ochronić przed tym błędem?
Zamienić load
na safe_load
.

Wtedy wszystkie niebezpieczne tagi przestaną działać.
Szkoda, że nie jest to standardowy sposób w jaki działa ta funkcja ponieważ myślę, że sporo osób nie zdaje sobie sprawy z niebezpieczeństwa.
