From b27baadcf549135b728647689a3dafe818de8cc4 Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 29 Sep 2025 12:08:40 +0000 Subject: [PATCH] Translated ['', 'src/generic-methodologies-and-resources/python/keras-mo --- ...-deserialization-rce-and-gadget-hunting.md | 147 ++++++++++++------ 1 file changed, 97 insertions(+), 50 deletions(-) diff --git a/src/generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md b/src/generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md index a55bb1ba6..9f66234f9 100644 --- a/src/generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md +++ b/src/generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md @@ -2,18 +2,18 @@ {{#include ../../banners/hacktricks-training.md}} -Questa pagina riassume le tecniche di sfruttamento pratico contro il pipeline di deserializzazione del modello Keras, spiega gli interni del formato .keras e la superficie di attacco, e fornisce un toolkit per i ricercatori per trovare Vulnerabilità dei File Modello (MFV) e gadget post-fix. +Questa pagina riassume tecniche pratiche di exploitation contro la pipeline di deserializzazione dei modelli Keras, spiega gli internals del formato nativo .keras e la sua attack surface, e fornisce un toolkit per ricercatori per trovare Model File Vulnerabilities (MFVs) e post-fix gadgets. -## Interni del formato modello .keras +## Interni del formato del modello .keras Un file .keras è un archivio ZIP che contiene almeno: -- metadata.json – informazioni generiche (ad es., versione Keras) -- config.json – architettura del modello (superficie di attacco principale) +- metadata.json – informazioni generiche (es., versione di Keras) +- config.json – architettura del modello (primary attack surface) - model.weights.h5 – pesi in HDF5 -Il config.json guida la deserializzazione ricorsiva: Keras importa moduli, risolve classi/funzioni e ricostruisce strati/oggetti da dizionari controllati dall'attaccante. +Il config.json controlla la deserializzazione ricorsiva: Keras importa moduli, risolve classi/funzioni e ricostruisce layer/oggetti da dizionari controllati dall'attaccante. -Esempio di frammento per un oggetto di strato Dense: +Example snippet for a Dense layer object: ```json { "module": "keras.layers", @@ -31,22 +31,22 @@ Esempio di frammento per un oggetto di strato Dense: } } ``` -Deserialization esegue: -- Importazione di moduli e risoluzione di simboli dalle chiavi module/class_name -- invocazione di from_config(...) o del costruttore con kwargs controllati dall'attaccante -- Ricorsione in oggetti annidati (attivazioni, inizializzatori, vincoli, ecc.) +Deserialization performs: +- Module import and symbol resolution from module/class_name keys +- from_config(...) or constructor invocation with attacker-controlled kwargs +- Recursion into nested objects (activations, initializers, constraints, etc.) -Storicamente, questo ha esposto tre primitive a un attaccante che crea config.json: +Storicamente, questo esponeva tre primitive a un attaccante che costruiva config.json: - Controllo di quali moduli vengono importati - Controllo di quali classi/funzioni vengono risolte -- Controllo di kwargs passati ai costruttori/from_config +- Controllo dei kwargs passati ai costruttori/from_config -## CVE-2024-3660 – RCE bytecode Lambda-layer +## CVE-2024-3660 – Lambda-layer bytecode RCE -Causa principale: -- Lambda.from_config() utilizzava python_utils.func_load(...) che decodifica in base64 e chiama marshal.loads() sui byte dell'attaccante; la deserializzazione di Python può eseguire codice. +Root cause: +- Lambda.from_config() used python_utils.func_load(...) which base64-decodes and calls marshal.loads() on attacker bytes; Python unmarshalling can execute code. -Idea di exploit (payload semplificato in config.json): +Exploit idea (simplified payload in config.json): ```json { "module": "keras.layers", @@ -61,18 +61,18 @@ Idea di exploit (payload semplificato in config.json): } ``` Mitigazione: -- Keras imposta safe_mode=True per impostazione predefinita. Le funzioni Python serializzate in Lambda sono bloccate a meno che un utente non scelga esplicitamente di disattivare con safe_mode=False. +- Keras enforces safe_mode=True by default. Serialized Python functions in Lambda are blocked unless a user explicitly opts out with safe_mode=False. Note: -- I formati legacy (salvataggi HDF5 più vecchi) o le codebase più vecchie potrebbero non applicare controlli moderni, quindi gli attacchi in stile "downgrade" possono ancora applicarsi quando le vittime utilizzano loader più vecchi. +- I formati legacy (vecchi salvataggi HDF5) o codebase più datate potrebbero non applicare i controlli moderni, quindi gli attacchi in stile “downgrade” possono ancora applicarsi quando le vittime usano loader più vecchi. -## CVE-2025-1550 – Importazione di moduli arbitrari in Keras ≤ 3.8 +## CVE-2025-1550 – Import arbitrario di moduli in Keras ≤ 3.8 Causa principale: -- _retrieve_class_or_fn utilizzava importlib.import_module() senza restrizioni con stringhe di moduli controllate dall'attaccante da config.json. -- Impatto: Importazione arbitraria di qualsiasi modulo installato (o modulo piantato dall'attaccante su sys.path). Il codice viene eseguito al momento dell'importazione, quindi si verifica la costruzione dell'oggetto con kwargs dell'attaccante. +- _retrieve_class_or_fn usava importlib.import_module() senza restrizioni con stringhe di modulo controllate dall'attaccante provenienti da config.json. +- Impatto: import arbitrario di qualsiasi modulo installato (o di un modulo piazzato dall'attaccante su sys.path). Il codice all'import viene eseguito, poi la costruzione dell'oggetto avviene con kwargs controllati dall'attaccante. -Idea di sfruttamento: +Exploit idea: ```json { "module": "maliciouspkg", @@ -81,15 +81,15 @@ Idea di sfruttamento: } ``` Miglioramenti della sicurezza (Keras ≥ 3.9): -- Elenco di moduli consentiti: importazioni limitate ai moduli ufficiali dell'ecosistema: keras, keras_hub, keras_cv, keras_nlp +- Allowlist dei moduli: import limitati ai moduli dell'ecosistema ufficiale: keras, keras_hub, keras_cv, keras_nlp - Modalità sicura predefinita: safe_mode=True blocca il caricamento di funzioni serializzate Lambda non sicure -- Controllo dei tipi di base: gli oggetti deserializzati devono corrispondere ai tipi attesi +- Controllo di tipo di base: gli oggetti deserializzati devono corrispondere ai tipi attesi -## Superficie gadget post-fix all'interno dell'elenco consentito +## Superficie dei gadget post-fix nella allowlist -Anche con l'elenco consentito e la modalità sicura, rimane una superficie ampia tra le chiamate Keras consentite. Ad esempio, keras.utils.get_file può scaricare URL arbitrari in posizioni selezionabili dall'utente. +Anche con l'allowlisting e la safe mode, rimane una superficie ampia tra i callables di Keras consentiti. Per esempio, keras.utils.get_file può scaricare URL arbitrari in posizioni selezionabili dall'utente. -Gadget tramite Lambda che fa riferimento a una funzione consentita (non bytecode Python serializzato): +Gadget via Lambda che fa riferimento a una funzione consentita (non bytecode Python serializzato): ```json { "module": "keras.layers", @@ -105,19 +105,19 @@ Gadget tramite Lambda che fa riferimento a una funzione consentita (non bytecode } } ``` -Importante limitazione: -- Lambda.call() aggiunge il tensore di input come primo argomento posizionale quando invoca il callable target. I gadget scelti devono tollerare un argomento posizionale extra (o accettare *args/**kwargs). Questo limita quali funzioni sono valide. +Limitazione importante: +- Lambda.call() antepone il tensor di input come primo argomento posizionale quando viene invocato il callable target. I gadget scelti devono tollerare un argomento posizionale extra (o accettare *args/**kwargs). Questo vincola quali funzioni sono utilizzabili. -Impatti potenziali dei gadget autorizzati: -- Download/scrittura arbitraria (piantagione di percorsi, avvelenamento della configurazione) -- Callback di rete/effetti simili a SSRF a seconda dell'ambiente -- Collegamento all'esecuzione del codice se i percorsi scritti vengono successivamente importati/eseguiti o aggiunti a PYTHONPATH, o se esiste una posizione di esecuzione scrivibile +Possibili impatti degli allowlisted gadgets: +- Download/scrittura arbitraria (path planting, config poisoning) +- Callback di rete / effetti simili a SSRF a seconda dell'ambiente +- Possibilità di esecuzione di codice se i percorsi scritti vengono poi importati/eseguiti o aggiunti a PYTHONPATH, o se esiste una location scrivibile che esegue al momento della scrittura (execution-on-write) -## Toolkit del ricercatore +## Toolkit per i ricercatori -1) Scoperta sistematica di gadget nei moduli consentiti +1) Scoperta sistematica dei gadget nei moduli consentiti -Enumerare i callable candidati tra keras, keras_nlp, keras_cv, keras_hub e dare priorità a quelli con effetti collaterali su file/rete/processo/ambiente. +Enumerare i callable candidati in keras, keras_nlp, keras_cv, keras_hub e dare priorità a quelli con effetti collaterali su file/rete/processo/ambiente. ```python import importlib, inspect, pkgutil @@ -160,9 +160,9 @@ candidates.append(text) print("\n".join(sorted(candidates)[:200])) ``` -2) Test di deserializzazione diretta (nessun archivio .keras necessario) +2) Test diretto di deserialization (nessun archivio .keras necessario) -Fornire dizionari creati direttamente ai deserializzatori Keras per apprendere i parametri accettati e osservare gli effetti collaterali. +Inserisci dicts appositamente creati direttamente nei deserializers di Keras per apprendere i params accettati e osservare gli effetti collaterali. ```python from keras import layers @@ -178,24 +178,65 @@ cfg = { layer = layers.deserialize(cfg, safe_mode=True) # Observe behavior ``` -3) Probing e formati tra versioni +3) Cross-version probing and formats -Keras esiste in più codebase/epoche con diverse protezioni e formati: -- Keras integrato in TensorFlow: tensorflow/python/keras (legacy, previsto per la cancellazione) +Keras esiste in più codebase/ere con diversi meccanismi di sicurezza e formati: +- TensorFlow built-in Keras: tensorflow/python/keras (legacy, previsto per la rimozione) - tf-keras: mantenuto separatamente -- Keras 3 multi-backend (ufficiale): introdotto il .keras nativo +- Multi-backend Keras 3 (official): ha introdotto il formato nativo .keras -Ripeti i test tra codebase e formati (.keras vs legacy HDF5) per scoprire regressioni o protezioni mancanti. +Ripetere i test attraverso codebase e formati (.keras vs legacy HDF5) per scoprire regressioni o protezioni mancanti. -## Raccomandazioni difensive +## Defensive recommendations -- Tratta i file modello come input non attendibili. Carica modelli solo da fonti fidate. -- Tieni Keras aggiornato; usa Keras ≥ 3.9 per beneficiare di allowlisting e controlli di tipo. -- Non impostare safe_mode=False quando carichi modelli a meno che non ti fidi completamente del file. -- Considera di eseguire la deserializzazione in un ambiente sandboxed, con privilegi minimi, senza uscita di rete e con accesso al filesystem ristretto. -- Applica allowlists/firme per le fonti dei modelli e controlli di integrità dove possibile. +- Trattare i file modello come input non attendibili. Caricare modelli solo da sorgenti trusted. +- Tenere Keras aggiornato; usare Keras ≥ 3.9 per beneficiare di allowlisting e controlli di tipo. +- Non impostare safe_mode=False quando si caricano modelli a meno che non si abbia completa fiducia nel file. +- Considerare di eseguire la deserializzazione in un ambiente sandboxed e least-privileged senza accesso di rete in uscita e con accesso al filesystem ristretto. +- Applicare allowlists/signatures per le sorgenti dei modelli e controlli di integrità quando possibile. -## Riferimenti +## ML pickle import allowlisting for AI/ML models (Fickling) + +Molti formati di modelli AI/ML (PyTorch .pt/.pth/.ckpt, joblib/scikit-learn, vecchi artifact TensorFlow, ecc.) incorporano dati Python pickle. Gli aggressori abusano regolarmente degli import GLOBAL di pickle e dei costruttori di oggetti per ottenere RCE o sostituzione del modello durante il caricamento. I scanner basati su blacklist spesso non rilevano import pericolosi nuovi o non elencati. + +Una difesa pratica fail-closed è agganciare il deserializer pickle di Python e consentire solo un set revisionato di import innocui correlati all’ML durante l’unpickling. Trail of Bits’ Fickling implementa questa policy e distribuisce una allowlist di import ML curata, costruita a partire da migliaia di pickles pubblici su Hugging Face. + +Modello di sicurezza per import “sicuri” (intuizioni distillate da ricerca e pratica): i simboli importati usati da un pickle devono simultaneamente: +- Non eseguire codice o causare esecuzione (niente oggetti compiled/source code, esecuzione di comandi esterni, hook, ecc.) +- Non ottenere/impostare attributi o elementi arbitrari +- Non importare o ottenere riferimenti ad altri oggetti Python dalla VM del pickle +- Non innescare deserializer secondari (es. marshal, nested pickle), neanche indirettamente + +Abilitare le protezioni di Fickling il prima possibile nell’avvio del processo in modo che eventuali caricamenti di pickle effettuati da framework (torch.load, joblib.load, ecc.) siano verificati: +```python +import fickling +# Sets global hooks on the stdlib pickle module +fickling.hook.activate_safe_ml_environment() +``` +Suggerimenti operativi: +- Puoi disabilitare/riabilitare temporaneamente gli hooks dove necessario: +```python +fickling.hook.deactivate_safe_ml_environment() +# ... load fully trusted files only ... +fickling.hook.activate_safe_ml_environment() +``` +- Se un modello noto come valido è bloccato, estendi la allowlist per il tuo ambiente dopo aver esaminato i simboli: +```python +fickling.hook.activate_safe_ml_environment(also_allow=[ +"package.subpackage.safe_symbol", +"another.safe.import", +]) +``` +- Fickling espone anche dei guard di runtime generici se preferisci un controllo più granulare: +- fickling.always_check_safety() per applicare i controlli su tutti i pickle.load() +- with fickling.check_safety(): per enforcement limitato (scoped) +- fickling.load(path) / fickling.is_likely_safe(path) per controlli one-off + +- Preferisci formati di modello non-pickle quando possibile (es., SafeTensors). Se devi accettare pickle, esegui i loader con least privilege, senza network egress e applica l'allowlist. + +Questa strategia allowlist-first blocca dimostrabilmente i percorsi di exploit comuni dei pickle ML mantenendo un'elevata compatibilità. Nel benchmark di ToB, Fickling ha segnalato il 100% dei file dannosi sintetici e ha consentito ~99% dei file puliti provenienti dai principali repo di Hugging Face. + +## References - [Hunting Vulnerabilities in Keras Model Deserialization (huntr blog)](https://blog.huntr.com/hunting-vulnerabilities-in-keras-model-deserialization) - [Keras PR #20751 – Added checks to serialization](https://github.com/keras-team/keras/pull/20751) @@ -203,5 +244,11 @@ Ripeti i test tra codebase e formati (.keras vs legacy HDF5) per scoprire regres - [CVE-2025-1550 – Keras arbitrary module import (≤ 3.8)](https://nvd.nist.gov/vuln/detail/CVE-2025-1550) - [huntr report – arbitrary import #1](https://huntr.com/bounties/135d5dcd-f05f-439f-8d8f-b21fdf171f3e) - [huntr report – arbitrary import #2](https://huntr.com/bounties/6fcca09c-8c98-4bc5-b32c-e883ab3e4ae3) +- [Trail of Bits blog – Fickling’s new AI/ML pickle file scanner](https://blog.trailofbits.com/2025/09/16/ficklings-new-ai/ml-pickle-file-scanner/) +- [Fickling – Securing AI/ML environments (README)](https://github.com/trailofbits/fickling#securing-aiml-environments) +- [Fickling pickle scanning benchmark corpus](https://github.com/trailofbits/fickling/tree/master/pickle_scanning_benchmark) +- [Picklescan](https://github.com/mmaitre314/picklescan), [ModelScan](https://github.com/protectai/modelscan), [model-unpickler](https://github.com/goeckslab/model-unpickler) +- [Sleepy Pickle attacks background](https://blog.trailofbits.com/2024/06/11/exploiting-ml-models-with-pickle-file-attacks-part-1/) +- [SafeTensors project](https://github.com/safetensors/safetensors) {{#include ../../banners/hacktricks-training.md}}