
Декомпилятор и статический анализатор Python pickling

Fickling — это декомпилятор, статический анализатор и перезаписыватель байт-кода для сериализации объектов Python pickle. Вы можете использовать Fickling для обнаружения, анализа, реверс-инжиниринга или даже создания вредоносных pickle-файлов и файлов на основе pickle, включая файлы PyTorch.
Fickling можно использовать как библиотеку Python, так и CLI.
Fickling протестирован на Python 3.9–3.13 и имеет очень мало зависимостей. И библиотеку, и утилиту командной строки можно установить через pip или uv:
# Using pip
python -m pip install fickling
# Using uv
uv pip install fickling
PyTorch является опциональной зависимостью Fickling. Поэтому для использования модулей pytorch
и polyglot Fickling выполните:
# Using pip
python -m pip install fickling[torch]
# Using uv
uv pip install fickling[torch]
Fickling может помочь защитить кодовые базы AI/ML, автоматически сканируя pickle-файлы, содержащиеся в моделях. Fickling перехватывает модуль pickle и проверяет импорты, выполняемые при загрузке модели. Он проверяет импорты только по белому списку импортов из библиотек ML, которые считаются безопасными, и блокирует файлы, содержащие другие импорты.
Добавьте следующие строки как можно раньше, до импорта torch, numpy или любой другой
библиотеки, использующей pickle:
import fickling
# This sets global hooks on pickle
fickling.hook.activate_safe_ml_environment()
Для снятия защиты:
fickling.hook.deactivate_safe_ml_environment()
Возможно, что модели, которые вы используете, содержат импорты, не разрешённые Fickling. Если вы всё же хотите загрузить модель, вы можете просто разрешить дополнительные импорты для вашего конкретного случая использования с помощью аргумента also_allow:
fickling.hook.activate_safe_ml_environment(
also_allow=[
"some.import",
"another.allowed.import",
]
)
Важно: Всегда убеждайтесь, что добавленные вручную импорты действительно безопасны и не позволяют злоумышленникам выполнять произвольный код. Если вы не уверены, как это сделать, вы можете открыть issue в репозитории Fickling на Github, указав проблемные импорты/модели, и наша команда сможет их проверить и, если возможно, включить в белый список.
Fickling можно легко интегрировать в вашу кодовую базу для обнаружения и остановки загрузки вредоносных файлов во время выполнения.
Ниже показаны различные способы использования Fickling для обеспечения проверок безопасности pickle-файлов.
Под капотом он перехватывает библиотеку pickle, добавляя проверки безопасности, так что при загрузке pickle-файла
возникает исключение UnsafeFileError, если в файле обнаружен вредоносный контент.
# This enforces safety checks every time pickle is used to deserialize
fickling.always_check_safety()
# Attempt to load an unsafe file now raises an exception
with open("file.pkl", "rb") as f:
try:
pickle.load(f)
except fickling.UnsafeFileError:
print("Unsafe file!")
with fickling.check_safety():
# All pickle files loaded within the context manager are checked for safety
try:
with open("file.pkl", "rb") as f:
pickle.load("file.pkl")
except fickling.UnsafeFileError:
print("Unsafe file!")
# Files loaded outside of context manager are NOT checked
pickle.load("file.pkl")
При выходе контекстный менеджер восстанавливает всё, что было установлено при входе, поэтому уже установленный хук остаётся в силе, а pickle не остаётся без хука.
# Use fickling.load() in place of pickle.load() to check safety and load a single pickle file
try:
fickling.load("file.pkl")
except fickling.UnsafeFileError as e:
print("Unsafe file!")
# Perform a safety check on a pickle file without loading it
if not fickling.is_likely_safe("file.pkl"):
print("Unsafe file!")
Вы можете получить доступ к деталям анализа безопасности Fickling из возникшего исключения:
>>> try:
... fickling.load("unsafe.pkl")
... except fickling.UnsafeFileError as e:
... print(e.info)
{
"severity": "OVERTLY_MALICIOUS",
"analysis": "Call to `eval(b'[5, 6, 7, 8]')` is almost certainly evidence of a malicious pickle file. Variable `_var0` is assigned value `eval(b'[5, 6, 7, 8]')` but unused afterward; this is suspicious and indicative of a malicious pickle file",
"detailed_results": {
"AnalysisResult": {
"OvertlyBadEval": "eval(b'[5, 6, 7, 8]')",
"UnusedVariables": [
"_var0",
"eval(b'[5, 6, 7, 8]')"
]
}
}
}
Если вы используете язык, отличный от Python, вы всё равно можете использовать CLI-интерфейс Fickling для проверки безопасности pickle-файлов:
fickling --check-safety -p pickled.data
CLI Fickling позволяет безопасно трассировать выполнение виртуальной машины Pickle без выполнения какого-либо вредоносного кода:
fickling --trace file.pkl
Fickling позволяет внедрять произвольный код в pickle-файл, который будет выполняться при каждой загрузке файла
fickling --inject "print('Malicious')" file.pkl > malicious.pkl
Fickling можно использовать для декомпиляции pickle-файла для дальнейшего анализа
>>> import ast, pickle
>>> from fickling.fickle import Pickled
>>> fickled_object = Pickled.load(pickle.dumps([1, 2, 3, 4]))
>>> print(ast.dump(fickled_object.ast, indent=4))
Module(
body=[
Assign(
targets=[
Name(id='result', ctx=Store())],
value=List(
elts=[
Constant(value=1),
Constant(value=2),
Constant(value=3),
Constant(value=4)],
ctx=Load()))],
type_ignores=[])
PyTorch содержит несколько файловых форматов, с помощью которых можно создавать полиглот-файлы — это файлы, которые могут быть корректно интерпретированы как более чем один файловый формат. Fickling поддерживает идентификацию, проверку и создание полиглотов со следующими форматами файлов PyTorch: