flawopen.com/Небезопасная десериализация/Безопасность pickle в Python
Безопасен ли pickle.load() для недоверенных данных?
Нет. Считайте pickle программой в посылке, а не пассивной записью: загрузка может запустить восстановление объекта до его проверки приложением. Для данных через границу доверия используйте формат, содержащий только данные.
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}
- Поток pickle:
- Специфичная для Python последовательность байтов с описанием восстановления объектов, включая ссылки на globals и поведение восстановления.
- Unpickling:
- Интерпретация потока и восстановление графа объектов; при этом могут вызываться функции.
- Граница доверия:
- Место, где пользователь, сервис, загрузка или общее хранилище может контролировать или менять байты.
- CWE-502:
- Десериализация недоверенных данных; ущерб зависит от возможности подменить данные, которые загружает приложение.
Недоверенные байты попадают в pickle
Загрузка, запрос, кэш или артефакт могут передать процессу данные pickle, контролируемые или изменённые атакующим.
Unpickler разрешает globals
Интерпретатор обрабатывает инструкции восстановления; find_class() может импортировать и вернуть именованные globals, включая функции.
Загрузка запускает поведение
Инструкции могут вызывать функции во время load() или loads(), до проверки результата приложением.
Последствия зависят от прав процесса
Поведение выполняется с правами процесса Python. Сеть, секреты, файлы и изоляция определяют масштаб.
Почему загрузка pickle пересекает границу выполнения кода
Поток pickle может указывать globals и функции восстановления. При unpickling Unpickler.find_class() разрешает globals, включая функции; opcodes могут запускать восстановление. Опасна сама операция pickle.load() или pickle.loads() — отдельного последующего вызова execute нет. Получившийся код имеет права процесса. Это документированное свойство формата; не используйте pickle для обмена недоверенными данными.
Что исправляет JSON — и чего он не исправляет
Документация Python предупреждает: загрузка недоверенных или подменённых данных pickle может выполнить произвольный код, тогда как декодирование JSON само по себе не создаёт такой путь выполнения. JSON не проверяет ввод автоматически: ограничьте размер, требуйте ожидаемый верхний тип и поля, сверяйте значения со схемой и отдельно проверяйте авторизацию. Если старый процесс временно использует pickle, до загрузки аутентифицируйте точные байты защищённым ключом. Подпись подтверждает происхождение и целостность только при допущениях о ключе и не делает безопасными вредоносные данные доверенного подписанта. Перейдите на формат данных.
- ✓Удалите
pickle.load()иpickle.loads()из путей обработки запросов, загрузок, общих кэшей и артефактов неизвестного происхождения. - ✓Используйте JSON или формат данных; задайте лимит размера, схему, разрешённые поля, диапазоны значений и авторизацию endpoint.
- ✓Если внутренний доверенный процесс временно сохраняет pickle, проверяйте HMAC или подпись точных байтов до загрузки, защищайте ключ и ограничьте права процесса.
- ✓Найдите вызовы pickle в коде и потоках данных; выясните, кто может менять каждый источник, и перенесите или изолируйте рискованные места.
Частые вопросы
Переопределение find_class() может ограничить globals, но трудно доказать безопасность загрузчика для всех протоколов и доступного поведения. Для байтов, контролируемых пользователем, предпочтителен формат данных.
Да. JSON избегает выполнения кода при декодировании, но приложение всё равно должно проверять типы, поля, размер, значения и права. Разделяйте разбор JSON и бизнес-правила.
Первичные источники
- Документация Python — предупреждение pickle и ограничение globals
- Документация Python — декодер JSON
- CWE-502 — десериализация недоверенных данных