W Pythonie do serializacji (przekształcania obiektów w ciąg bajtów lub łańcuch do przechowywania/przesyłania) używane są moduły pickle i json:
Używanie Pickle do przechowywania/przesyłania danych między niekontrolowanymi stronami jest niebezpieczne, ponieważ podczas deserializacji można wykonać dowolny złośliwy kod. json nie ma tej wady.
Przykład działania:
import pickle import json # Pickle (serializacja binarna) data = {'x': 10, 'func': lambda x: x + 1} with open('data.pkl', 'wb') as f: pickle.dump(data, f) # JSON (tylko proste obiekty) data = {'x': 10, 'y': [1, 2, 3]} with open('data.json', 'w') as f: json.dump(data, f)
Pytanie: Czy można używać pickle do serializacji i przechowywania dowolnych obiektów Pythona między sesjami? Dlaczego ten mechanizm nie jest zalecany do przechowywania danych użytkowników?
Odpowiedź:
Nie, używanie pickle wszędzie to zła praktyka. Oprócz bezpieczeństwa (przy załadowaniu "cudzych" obiektów pickle'owanych wykonanie może być skompromitowane), istnieje problem zgodności wersji Pythona lub klas — zserializowane obiekty mogą nie załadować się lub zachować się niepoprawnie, jeśli struktura klas się zmieniła.
Przykład:
# Ładowanie pliku pickle, struktura klasy się zmieniła import pickle with open('old_version.pkl', 'rb') as f: obj = pickle.load(f) # AttributeError lub rozbieżność struktury
Historia
W dużym projekcie do przechowywania profili użytkowników używany był pickle. Po aktualizacji wersji Pythona i zmianie klas struktura zserializowanych obiektów straciła kompatybilność, co doprowadziło do awarii systemu i utraty większości danych użytkowników.
W serwisie internetowym pickle był używany do sesji użytkowników. Złośliwy użytkownik załadował złośliwy obiekt pickle, co pozwoliło na wykonanie wstrzyknięcia kodu na serwerze.
Próba serializacji funkcji za pomocą pickle w celu ich przesłania przez sieć zakończyła się niepowodzeniem w niektórych środowiskach: pickle'owane lambdy nie mogą zostać przeniesione między maszynami o różnych konfiguracjach/wersjach Pythona.