From 5940b8fe39f3a9d8bbb025150a374c6a7a431f26 Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 29 Sep 2025 12:09:36 +0000 Subject: [PATCH] Translated ['', 'src/generic-methodologies-and-resources/python/keras-mo --- ...-deserialization-rce-and-gadget-hunting.md | 155 ++++++++++++------ 1 file changed, 101 insertions(+), 54 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 011ba4ce6..2d38dc226 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,16 +2,16 @@ {{#include ../../banners/hacktricks-training.md}} -Ta strona podsumowuje praktyczne techniki eksploatacji przeciwko potokowi deserializacji modelu Keras, wyjaśnia wewnętrzne działanie formatu .keras oraz powierzchnię ataku, a także dostarcza narzędzi badawczych do znajdowania Wrażliwości Plików Modelu (MFV) i gadżetów po naprawie. +Ta strona podsumowuje praktyczne techniki eksploatacji przeciwko procesowi deserializacji modeli Keras, wyjaśnia wewnętrzną strukturę natywnego formatu .keras i powierzchnię ataku oraz dostarcza zestaw narzędzi dla badaczy do znajdowania Model File Vulnerabilities (MFVs) i post-fix gadgets. -## Wewnętrzne działanie formatu modelu .keras +## .keras model format internals -Plik .keras to archiwum ZIP zawierające przynajmniej: -- metadata.json – ogólne informacje (np. wersja Keras) -- config.json – architektura modelu (główna powierzchnia ataku) +Plik .keras to archiwum ZIP zawierające co najmniej: +- metadata.json – informacje ogólne (np. wersja Keras) +- config.json – architekturę modelu (główna powierzchnia ataku) - model.weights.h5 – wagi w HDF5 -Plik config.json napędza rekurencyjną deserializację: Keras importuje moduły, rozwiązuje klasy/funkcje i rekonstruuje warstwy/obiekty z kontrolowanych przez atakującego słowników. +Plik config.json steruje rekursywną deserializacją: Keras importuje moduły, rozwiązuje klasy/funkcje i rekonstruuje warstwy/obiekty ze słowników kontrolowanych przez atakującego. Przykładowy fragment dla obiektu warstwy Dense: ```json @@ -32,21 +32,21 @@ Przykładowy fragment dla obiektu warstwy Dense: } ``` Deserializacja wykonuje: -- Import modułów i rozwiązywanie symboli z kluczy module/class_name -- wywołanie from_config(...) lub konstruktora z kontrolowanymi przez atakującego kwargs -- Rekursję w zagnieżdżonych obiektach (aktywacje, inicjalizatory, ograniczenia itp.) +- Import modułów i rozwiązywanie symboli na podstawie kluczy module/class_name +- Wywołanie from_config(...) lub konstruktora z kwargs kontrolowanymi przez atakującego +- Rekurencja w głąb zagnieżdżonych obiektów (activations, initializers, constraints, etc.) -Historycznie, to ujawniało trzy prymitywy atakującemu tworzącemu config.json: -- Kontrola nad tym, jakie moduły są importowane -- Kontrola nad tym, które klasy/funkcje są rozwiązywane -- Kontrola nad kwargs przekazywanymi do konstruktorów/from_config +Historycznie umożliwiało to atakującemu tworzącemu config.json kontrolę nad trzema prymitywami: +- Kontrolę nad tym, które moduły są importowane +- Kontrolę nad tym, które klasy/funkcje są rozwiązywane +- Kontrolę nad kwargs przekazywanymi do konstruktorów/from_config -## CVE-2024-3660 – RCE z bajtkodem warstwy Lambda +## CVE-2024-3660 – Lambda-layer bytecode RCE Przyczyna: -- Lambda.from_config() używało python_utils.func_load(...), które dekoduje base64 i wywołuje marshal.loads() na bajtach atakującego; deserializacja w Pythonie może wykonać kod. +- Lambda.from_config() używało python_utils.func_load(...), które base64-dekoduje i wywołuje marshal.loads() na bajtach dostarczonych przez atakującego; odmarshalowywanie w Pythonie może wykonać kod. -Pomysł na exploit (uproszczony ładunek w config.json): +Pomysł exploita (uproszczony payload w config.json): ```json { "module": "keras.layers", @@ -61,16 +61,16 @@ Pomysł na exploit (uproszczony ładunek w config.json): } ``` Mitigacja: -- Keras domyślnie wymusza safe_mode=True. Zserializowane funkcje Pythona w Lambda są zablokowane, chyba że użytkownik wyraźnie zdecyduje się na safe_mode=False. +- Keras narzuca safe_mode=True domyślnie. Serializowane funkcje Pythona w Lambda są blokowane, chyba że użytkownik wyraźnie zrezygnuje, ustawiając safe_mode=False. Uwagi: -- Starsze formaty (starsze zapisy HDF5) lub starsze bazy kodu mogą nie wymuszać nowoczesnych kontroli, więc ataki w stylu „downgrade” mogą nadal mieć zastosowanie, gdy ofiary używają starszych loaderów. +- Starsze formaty (wcześniejsze zapisy HDF5) lub starsze bazy kodu mogą nie wymuszać nowoczesnych kontroli, więc ataki w stylu „downgrade” mogą nadal mieć zastosowanie, gdy ofiary używają starszych loaderów. ## CVE-2025-1550 – Dowolny import modułu w Keras ≤ 3.8 Przyczyna: -- _retrieve_class_or_fn używał nieograniczonego importlib.import_module() z ciągami modułów kontrolowanymi przez atakującego z config.json. -- Wpływ: Dowolny import dowolnego zainstalowanego modułu (lub modułu umieszczonego przez atakującego na sys.path). Kod uruchamia się w czasie importu, a następnie następuje konstrukcja obiektu z kwargs atakującego. +- _retrieve_class_or_fn używał nieograniczonego importlib.import_module() z ciągami modułów kontrolowanymi przez atakującego pochodzącymi z config.json. +- Wpływ: Dowolny import dowolnego zainstalowanego modułu (lub modułu podstawionego przez atakującego na sys.path). Kod uruchamiany podczas importu zostaje wykonany, a następnie następuje konstrukcja obiektu z przekazanymi przez atakującego kwargs. Pomysł na exploit: ```json @@ -80,16 +80,16 @@ Pomysł na exploit: "config": {"arg": "val"} } ``` -Poprawki bezpieczeństwa (Keras ≥ 3.9): -- Lista dozwolonych modułów: importy ograniczone do oficjalnych modułów ekosystemu: keras, keras_hub, keras_cv, keras_nlp -- Domyślny tryb bezpieczny: safe_mode=True blokuje ładowanie niebezpiecznych funkcji zserializowanych Lambda +Ulepszenia bezpieczeństwa (Keras ≥ 3.9): +- Module allowlist: importy ograniczone do oficjalnych modułów ekosystemu: keras, keras_hub, keras_cv, keras_nlp +- Domyślny safe mode: safe_mode=True blokuje ładowanie niebezpiecznych Lambda serialized-function - Podstawowe sprawdzanie typów: zdeserializowane obiekty muszą odpowiadać oczekiwanym typom -## Powierzchnia gadżetów po poprawce wewnątrz listy dozwolonych +## Powierzchnia post-fix gadget wewnątrz allowlist -Nawet z listą dozwolonych i trybem bezpiecznym, pozostaje szeroka powierzchnia wśród dozwolonych wywołań Keras. Na przykład, keras.utils.get_file może pobierać dowolne adresy URL do lokalizacji wybranych przez użytkownika. +Nawet przy allowlisting i safe mode, wśród dozwolonych Keras callables nadal istnieje szeroka powierzchnia ataku. Na przykład, keras.utils.get_file może pobierać dowolne URLs do lokalizacji wybranych przez użytkownika. -Gadżet przez Lambda, który odnosi się do dozwolonej funkcji (nie zserializowany bajtkod Pythona): +Gadget przez Lambda, który odwołuje się do dozwolonej funkcji (nie zserializowany Python bytecode): ```json { "module": "keras.layers", @@ -105,19 +105,19 @@ Gadżet przez Lambda, który odnosi się do dozwolonej funkcji (nie zserializowa } } ``` -Important limitation: -- Lambda.call() dodaje tensor wejściowy jako pierwszy argument pozycyjny podczas wywoływania docelowego wywołania. Wybrane gadżety muszą tolerować dodatkowy argument pozycyjny (lub akceptować *args/**kwargs). Ogranicza to, które funkcje są wykonalne. +Ważne ograniczenie: +- Lambda.call() prepends the input tensor as the first positional argument when invoking the target callable. Chosen gadgets must tolerate an extra positional arg (or accept *args/**kwargs). This constrains which functions are viable. -Potential impacts of allowlisted gadgets: -- Dowolne pobieranie/zapisywanie (sadzenie ścieżek, zanieczyszczanie konfiguracji) -- Wywołania sieciowe/efekty podobne do SSRF w zależności od środowiska -- Łączenie do wykonania kodu, jeśli zapisane ścieżki są później importowane/wykonywane lub dodawane do PYTHONPATH, lub jeśli istnieje zapisywalna lokalizacja do wykonania przy zapisie +Potencjalne skutki dopuszczonych gadżetów: +- Dowolne pobieranie/zapisywanie (path planting, config poisoning) +- Network callbacks/SSRF-like effects depending on environment +- Możliwość doprowadzenia do wykonania kodu, jeśli zapisane ścieżki są później importowane/uruchamiane lub dodane do PYTHONPATH, albo jeśli istnieje zapisywalna lokalizacja wykonująca kod przy zapisie -## Researcher toolkit +## Zestaw narzędzi badawczych 1) Systematyczne odkrywanie gadżetów w dozwolonych modułach -Enumeruj kandydatów na wywołania w keras, keras_nlp, keras_cv, keras_hub i nadaj priorytet tym z efektami ubocznymi związanymi z plikami/siecią/procesem/środowiskiem. +Wypisz kandydackie callables w ramach keras, keras_nlp, keras_cv, keras_hub i nadaj priorytet tym, które mają skutki uboczne dotyczące plików/sieci/procesów/środowiska. ```python import importlib, inspect, pkgutil @@ -160,9 +160,9 @@ candidates.append(text) print("\n".join(sorted(candidates)[:200])) ``` -2) Bezpośrednie testowanie deserializacji (nie jest potrzebny archiwum .keras) +2) Bezpośrednie testowanie deserializacji (archiwum .keras nie jest wymagane) -Wprowadź przygotowane słowniki bezpośrednio do deserializatorów Keras, aby poznać akceptowane parametry i obserwować efekty uboczne. +Podawaj przygotowane dicts bezpośrednio do Keras deserializers, aby poznać akceptowane params i obserwować efekty uboczne. ```python from keras import layers @@ -178,30 +178,77 @@ cfg = { layer = layers.deserialize(cfg, safe_mode=True) # Observe behavior ``` -3) Probing między wersjami i formaty +3) Sondowanie międzywersyjne i formaty -Keras istnieje w wielu bazach kodu/epokach z różnymi zabezpieczeniami i formatami: -- Wbudowany Keras w TensorFlow: tensorflow/python/keras (legacy, planowane do usunięcia) -- tf-keras: utrzymywany osobno -- Multi-backend Keras 3 (oficjalny): wprowadzono natywny .keras +Keras występuje w wielu repozytoriach/epokach z różnymi zabezpieczeniami i formatami: +- TensorFlow built-in Keras: tensorflow/python/keras (legacy, slated for deletion) +- tf-keras: maintained separately +- Multi-backend Keras 3 (official): introduced native .keras -Powtarzaj testy w różnych bazach kodu i formatach (.keras vs legacy HDF5), aby odkryć regresje lub brakujące zabezpieczenia. +Powtarzaj testy w różnych repozytoriach i formatach (.keras vs legacy HDF5), aby wykryć regresje lub brakujące zabezpieczenia. -## Rekomendacje defensywne +## Zalecenia obronne -- Traktuj pliki modeli jako niezaufane dane wejściowe. Ładuj modele tylko z zaufanych źródeł. -- Utrzymuj Keras w najnowszej wersji; używaj Keras ≥ 3.9, aby skorzystać z list dozwolonych i sprawdzania typów. -- Nie ustawiaj safe_mode=False podczas ładowania modeli, chyba że w pełni ufasz plikowi. -- Rozważ uruchomienie deserializacji w piaskownicy, w środowisku o minimalnych uprawnieniach, bez dostępu do sieci i z ograniczonym dostępem do systemu plików. -- Wprowadź listy dozwolone/podpisy dla źródeł modeli i sprawdzania integralności, gdzie to możliwe. +- Traktuj pliki modeli jako niezaufane dane wejściowe. Ładuj modele tylko ze zaufanych źródeł. +- Utrzymuj Keras zaktualizowany; używaj Keras ≥ 3.9, aby skorzystać z allowlisting i kontroli typów. +- Nie ustawiaj safe_mode=False przy ładowaniu modeli, chyba że w pełni ufasz plikowi. +- Rozważ uruchamianie deserializacji w sandboxie z minimalnymi uprawnieniami, bez dostępu do sieci wychodzącej i z ograniczonym dostępem do systemu plików. +- Wymuszaj allowlists/sygnatury dla źródeł modeli i sprawdzanie integralności tam, gdzie to możliwe. -## Odniesienia +## ML pickle import allowlisting for AI/ML models (Fickling) -- [Hunting Vulnerabilities in Keras Model Deserialization (blog huntr)](https://blog.huntr.com/hunting-vulnerabilities-in-keras-model-deserialization) -- [Keras PR #20751 – Dodano kontrole do serializacji](https://github.com/keras-team/keras/pull/20751) +Wiele formatów modeli AI/ML (PyTorch .pt/.pth/.ckpt, joblib/scikit-learn, starsze artefakty TensorFlow itp.) osadza dane Python pickle. Atakujący rutynowo nadużywają pickle GLOBAL imports i konstruktorów obiektów, aby osiągnąć RCE lub podmianę modelu podczas ładowania. Skanery oparte na czarnej liście często nie wykrywają nowych lub nieujętych niebezpiecznych importów. + +Praktyczna, fail-closed strategia obronna polega na zahaczeniu deserializatora pickle Pythona i zezwoleniu tylko na przeglądany zestaw nieszkodliwych importów związanych z ML podczas unpicklingu. Trail of Bits’ Fickling implementuje tę politykę i dostarcza wyselekcjonowaną ML import allowlist zbudowaną na podstawie tysięcy publicznych pickli z Hugging Face. + +Model bezpieczeństwa dla „bezpiecznych” importów (intuicje wyprowadzone z badań i praktyki): symbole importowane i używane przez pickle muszą jednocześnie: +- Nie wykonywać kodu ani nie powodować jego wykonania (np. brak obiektów reprezentujących kod, uruchamiania poleceń shell, hooków itp.) +- Nie pobierać ani nie ustawiać dowolnych atrybutów lub elementów +- Nie importować ani nie pozyskiwać referencji do innych obiektów Pythona z VM pickla +- Nie uruchamiać żadnych wtórnych deserializatorów (np. marshal, nested pickle), nawet pośrednio + +Włącz ochrony Fickling jak najwcześniej podczas uruchamiania procesu, tak aby wszystkie ładowania pickle wykonywane przez frameworki (torch.load, joblib.load, itp.) były sprawdzane: +```python +import fickling +# Sets global hooks on the stdlib pickle module +fickling.hook.activate_safe_ml_environment() +``` +Wskazówki operacyjne: +- Możesz tymczasowo wyłączyć/ponownie włączyć hooks tam, gdzie to potrzebne: +```python +fickling.hook.deactivate_safe_ml_environment() +# ... load fully trusted files only ... +fickling.hook.activate_safe_ml_environment() +``` +Jeśli zablokowano sprawdzony model, rozszerz allowlist dla swojego środowiska po przejrzeniu symboli: +```python +fickling.hook.activate_safe_ml_environment(also_allow=[ +"package.subpackage.safe_symbol", +"another.safe.import", +]) +``` +- Fickling udostępnia też ogólne runtime guards, jeśli wolisz bardziej granulowaną kontrolę: +- fickling.always_check_safety() aby wymusić sprawdzenia dla wszystkich wywołań pickle.load() +- with fickling.check_safety(): dla wymuszania w określonym zakresie +- fickling.load(path) / fickling.is_likely_safe(path) do jednorazowych kontroli + +- W miarę możliwości preferuj formaty modeli inne niż pickle (np. SafeTensors). Jeśli musisz akceptować pickle, uruchamiaj ładowarki z najmniejszymi uprawnieniami, bez egressu sieciowego, i egzekwuj allowlistę. + +Ta strategia oparta na allowliście dowodnie blokuje typowe ścieżki exploitów pickle w ML, zachowując przy tym wysoką kompatybilność. W benchmarku ToB, Fickling oznaczył 100% syntetycznych złośliwych plików i dopuścił ~99% czystych plików z czołowych repozytoriów Hugging Face. + +## Źródła + +- [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) - [CVE-2024-3660 – Keras Lambda deserialization RCE](https://nvd.nist.gov/vuln/detail/CVE-2024-3660) -- [CVE-2025-1550 – Keras dowolny import modułu (≤ 3.8)](https://nvd.nist.gov/vuln/detail/CVE-2025-1550) -- [raport huntr – dowolny import #1](https://huntr.com/bounties/135d5dcd-f05f-439f-8d8f-b21fdf171f3e) -- [raport huntr – dowolny import #2](https://huntr.com/bounties/6fcca09c-8c98-4bc5-b32c-e883ab3e4ae3) +- [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}}