flawopen.com/Désérialisation non sécurisée/Sécurité du pickle Python
pickle.load() est-il sûr avec des données non fiables ?
Non. Considérez pickle comme un programme dans un colis, pas comme un simple enregistrement : le chargement peut déclencher la reconstruction avant la validation de l’objet. Utilisez un format limité aux données pour toute entrée franchissant une frontière de confiance.
import pickle # Never accept pickle bytes from a request, upload, # shared cache, or other untrusted source. obj = pickle.loads(untrusted_bytes)
import json
def parse_profile(raw: bytes) -> dict[str, str]:
if len(raw) > 65_536:
raise ValueError("Payload too large")
try:
value = json.loads(raw)
except (json.JSONDecodeError, UnicodeDecodeError):
raise ValueError("Invalid JSON") from None
if not isinstance(value, dict) or set(value) - {"display_name", "theme"}:
raise ValueError("Invalid profile")
name = value.get("display_name")
theme = value.get("theme")
if not isinstance(name, str) or len(name) > 80:
raise ValueError("Invalid display name")
if theme not in {"light", "dark"}:
raise ValueError("Invalid theme")
return {"display_name": name, "theme": theme}
- Flux pickle :
- Suite d’octets propre à Python décrivant la reconstruction d’objets, avec des références aux globaux et au comportement de reconstruction.
- Unpickling :
- Interprétation du flux et reconstruction du graphe d’objets ; des fonctions peuvent être appelées.
- Frontière de confiance :
- Point où un utilisateur, service, téléversement ou stockage partagé peut contrôler ou modifier les octets.
- CWE-502 :
- Désérialisation de données non fiables ; l’impact dépend de la possibilité de fournir ou modifier les données chargées.
Des octets non fiables atteignent pickle
Un téléversement, une requête, un cache ou un artefact peut transmettre des données pickle contrôlées ou altérées au processus.
L’unpickler résout les globaux
L’interpréteur traite les instructions de reconstruction ; find_class() peut importer et renvoyer des globaux nommés, y compris des fonctions.
Le chargement déclenche un comportement
Les instructions peuvent appeler des fonctions pendant load() ou loads(), avant la validation de l’objet retourné.
L’impact dépend des droits du processus
Le comportement s’exécute avec les droits du processus Python. Réseau, secrets, fichiers et isolation déterminent le rayon d’impact.
Pourquoi le chargement pickle franchit une frontière d’exécution de code
Un flux pickle peut nommer des globaux et des fonctions de reconstruction. Pendant l’unpickling, Unpickler.find_class() résout les globaux, y compris les fonctions ; des opcodes peuvent déclencher la reconstruction. Le danger est pickle.load() ou pickle.loads() lui-même : aucun appel execute séparé ne suit. Le code obtenu dispose des droits du processus. C’est le comportement documenté du format ; n’utilisez pas pickle pour échanger des données non fiables.
Ce que JSON corrige — et ne corrige pas
La documentation Python avertit que charger des données pickle non fiables ou modifiées peut exécuter du code arbitraire, tandis que décoder du JSON ne crée pas à lui seul cette voie d’exécution. JSON ne valide pas l’entrée : limitez sa taille, exigez le type supérieur et les champs attendus, validez les valeurs selon un schéma et appliquez l’autorisation séparément. Si un ancien flux doit encore charger pickle, authentifiez les octets exacts avec une clé protégée avant le chargement ; une signature prouve l’origine et l’intégrité uniquement selon les hypothèses liées à la clé, et ne rend pas sûr un contenu malveillant signé par une source fiable. Migrez vers un format de données.
- ✓Retirez
pickle.load()etpickle.loads()des parcours qui consomment requêtes, téléversements, caches partagés ou artefacts d’origine incertaine. - ✓Utilisez JSON ou un autre format de données, avec limites de taille, schéma, champs autorisés, bornes de valeurs et autorisation de l’endpoint.
- ✓Si un flux interne de confiance conserve temporairement pickle, vérifiez HMAC ou signature sur les octets exacts avant chargement, protégez la clé et réduisez les droits du processus.
- ✓Recherchez les consommateurs pickle dans le code et les flux ; déterminez qui peut écrire ou modifier chaque source, puis migrez ou isolez les usages risqués.
Questions fréquentes
Redéfinir find_class() peut réduire le risque en limitant les globaux, mais prouver qu’un chargeur est sûr pour tous les protocoles et comportements accessibles est difficile. Pour des octets contrôlés par l’utilisateur, préférez un format de données.
Oui. JSON évite l’exécution de code propre à pickle lors du décodage, mais il faut valider types, champs, tailles, valeurs et autorisations. Séparez analyse JSON et règles métier.
Références principales
- Documentation Python — avertissement pickle et globaux restreints
- Documentation Python — décodeur JSON
- CWE-502 — Désérialisation de données non fiables