
Un decompilador de pickling de Python y analizador estático

Fickling es un descompilador, analizador estático y reescritor de bytecode para serializaciones de objetos pickle de Python. Puedes usar fickling para detectar, analizar, aplicar ingeniería inversa o incluso crear archivos pickle maliciosos o basados en pickle, incluidos archivos de PyTorch.
Fickling puede usarse tanto como biblioteca de python como CLI.
Fickling requiere Python 3.11 o superior y tiene muy pocas dependencias. Tanto la biblioteca como la utilidad de línea de comandos pueden instalarse mediante pip o uv:
# Using pip
python -m pip install fickling
# Using uv
uv pip install fickling
PyTorch es una dependencia opcional de Fickling. Por lo tanto, para usar los módulos pytorch y polyglot de Fickling, debes ejecutar:
# Using pip
python -m pip install fickling[torch]
# Using uv
uv pip install fickling[torch]
Fickling puede ayudar a proteger las bases de código de IA/ML escaneando automáticamente los archivos pickle contenidos en los modelos. Fickling intercepta el módulo pickle y verifica las importaciones realizadas al cargar un modelo. Solo comprueba las importaciones contra una lista de permitidos de importaciones de bibliotecas de ML consideradas seguras, y bloquea los archivos que contienen otras importaciones.
Añade las siguientes líneas lo antes posible, antes de importar torch, numpy o cualquier otra biblioteca que utilice pickle:
import fickling
# This sets global hooks on pickle
fickling.hook.activate_safe_ml_environment()
Para eliminar la protección:
fickling.hook.deactivate_safe_ml_environment()
Es posible que los modelos que estás utilizando contengan importaciones que no están permitidas por Fickling. Si aún deseas cargar el modelo, puedes simplemente permitir importaciones adicionales para tu caso de uso específico con el argumento also_allow:
fickling.hook.activate_safe_ml_environment(
also_allow=[
"some.import",
"another.allowed.import",
]
)
Importante: Siempre debes asegurarte de que las importaciones añadidas manualmente sean realmente seguras y no permitan a los atacantes ejecutar código arbitrario. Si no estás seguro de cómo hacerlo, puedes abrir un issue en el repositorio de GitHub de Fickling indicando las importaciones/modelos en cuestión, y nuestro equipo podrá revisarlos e incluirlos en la lista de permitidos si es posible.
Fickling puede integrarse sin problemas en tu base de código para detectar y detener la carga de archivos maliciosos en tiempo de ejecución.
A continuación mostramos las diferentes formas en que puedes usar fickling para aplicar comprobaciones de seguridad en archivos pickle. Internamente, engancha la librería pickle para añadir comprobaciones de seguridad de modo que la carga de un archivo pickle lance una excepción UnsafeFileError si se detecta contenido malicioso en el archivo.
# 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")
Al salir, el gestor de contexto restaura lo que estuviera instalado cuando se entró, de modo que un hook ya presente sigue en efecto en lugar de dejar pickle sin hook.
# 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!")
Puedes acceder a los detalles del análisis de seguridad de fickling desde dentro de la excepción generada:
>>> 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]')"
]
}
}
}
Si está utilizando un lenguaje distinto de Python, aún puede usar la CLI de fickling para
verificar la seguridad de los archivos pickle:
fickling --check-safety -p pickled.data
El CLI de Fickling permite rastrear de forma segura la ejecución de la máquina virtual de Pickle sin
ejecutar ningún código malicioso:
fickling --trace file.pkl
Fickling permite inyectar código arbitrario en un archivo pickle que se ejecutará cada vez que se cargue el archivo
fickling --inject "print('Malicious')" file.pkl > malicious.pkl
Fickling se puede utilizar para descompilar un archivo pickle para un análisis más detallado
>>> 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 contiene múltiples formatos de archivo con los que se pueden crear archivos polyglot, que son archivos que pueden interpretarse válidamente como más de un formato de archivo. Fickling permite identificar, inspeccionar y crear polyglots con los siguientes formatos de archivo de PyTorch: