mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['', 'src/generic-methodologies-and-resources/python/keras-mo
This commit is contained in:
		
							parent
							
								
									ef4acb5199
								
							
						
					
					
						commit
						5940b8fe39
					
				| @ -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}} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user