In Python worden de modules pickle en json gebruikt voor serialisatie (het omzetten van objecten naar een reeks bytes of een string voor opslag/verzending):
Het gebruik van pickle voor het opslaan/verzenden van gegevens tussen ongecontroleerde partijen is gevaarlijk, omdat bij deserialisatie willekeurige kwaadaardige code kan worden uitgevoerd. json heeft dit nadeel niet.
Voorbeeld van gebruik:
import pickle import json # Pickle (binaire serialisatie) data = {'x': 10, 'func': lambda x: x + 1} with open('data.pkl', 'wb') as f: pickle.dump(data, f) # JSON (alleen eenvoudige objecten) data = {'x': 10, 'y': [1, 2, 3]} with open('data.json', 'w') as f: json.dump(data, f)
Vraag: Kan pickle worden gebruikt voor het serialiseren en opslaan van willekeurige Python-objecten tussen sessies? Waarom wordt dit mechanisme niet aanbevolen voor het opslaan van gebruikersgegevens?
Antwoord:
Nee, het overal gebruiken van pickle is een slechte praktijk. Naast beveiliging (bij het laden van een "vreemd" pickled-object kan de uitvoering in gevaar komen), is er een probleem met versie-inconsistentie van Python of klassen — geserialiseerde objecten kunnen niet worden geladen of zich vreemd gedragen als de structuur van de klassen is gewijzigd.
Voorbeeld:
# Laden van een pickle-bestand, de structuur van de klasse is veranderd import pickle with open('old_version.pkl', 'rb') as f: obj = pickle.load(f) # AttributeError of structuurverschil
Geschiedenis
In een groot project werd pickle gebruikt voor het opslaan van gebruikersprofielen. Na een upgrade van de Python-versie en wijziging van klassen verloor de structuur van de geserialiseerde objecten zijn compatibiliteit, wat leidde tot systeemfouten en het verlies van de meeste gebruikersgegevens.
In een webdienst werd pickle gebruikt voor gebruikerssessies. Een kwaadwillende gebruiker laadde een kwaadaardig pickled-object, waardoor code-injectie op de server mogelijk werd.
De poging om functies te serialiseren via pickle voor netwerkoverdracht mislukte in verschillende omgevingen: pickled-lambdas kunnen niet worden overgedragen tussen machines met verschillende configuraties/versies van Python.