
No cenário atual de IA, modelos de machine learning tornaram-se ferramentas essenciais para as mais diversas tarefas — de visão computacional e processamento de linguagem natural a cibersegurança. Contudo, à medida que organizações integram cada vez mais modelos pré-treinados de repositórios públicos e terceiros, cresce o risco de modelos comprometidos na cadeia de suprimentos de IA. Neste artigo técnico detalhado, mergulhamos fundo nos backdoors persistentes em IA, com foco na técnica inovadora ShadowLogic, e exploramos como esses backdoors sobrevivem a conversões de modelo (por exemplo, PyTorch → ONNX → TensorRT) e a processos de fine-tuning. Também discutiremos como adversários podem explorar essas fragilidades, apresentaremos trechos de código detalhados e demonstraremos métodos de varredura e análise de saídas usando scripts Bash e Python. Seja você iniciante ou profissional avançado em cibersegurança e IA, este post proporcionará uma compreensão abrangente dos backdoors persistentes e suas implicações.
A Inteligência Artificial (IA) transformou indústrias ao automatizar tarefas, fornecer insights em escala e impulsionar produtos inovadores. Porém, a rápida proliferação de ferramentas de IA também expôs organizações a uma série de novas ameaças, entre elas o risco de envenenamento de modelos e ataques de backdoor.
Um backdoor em um modelo de machine learning é uma funcionalidade oculta implantada por um adversário. Quando um gatilho específico está presente nos dados de entrada, o modelo se desvia do comportamento esperado. Diferentemente dos backdoors em software tradicional, os backdoors em IA envolvem a manipulação do grafo computacional ou dos dados de treinamento, tornando-os inovadores e difíceis de detectar.
A cadeia de suprimentos de IA envolve várias etapas — desde a obtenção de modelos pré-treinados até o fine-tuning e a implantação em produção. Como muitas organizações dependem de modelos compartilhados por comunidades open source ou fornecedores terceirizados, existe a possibilidade de esses modelos terem sido sutilmente comprometidos. Um atacante que embute um backdoor pode garantir que o modelo se comporte normalmente sob condições padrão, mas produza saídas maliciosas quando um gatilho específico é ativado. A situação torna-se ainda mais perigosa quando técnicas de backdoor, como a ShadowLogic, permitem persistência mesmo após:
Neste post, focamos na técnica de ponta ShadowLogic, que demonstra uma resiliência sem precedentes contra fluxos de modificação comuns.
Backdoors persistentes são projetados para continuar eficazes mesmo após o modelo passar por transformações. Isso significa que a lógica maliciosa não desaparece quando o modelo é convertido para outro formato — por exemplo, de PyTorch (usado no treinamento) para ONNX (usado na implantação) ou ainda otimizado em TensorRT para inferência em GPUs NVIDIA.
A técnica ShadowLogic, descoberta por pesquisadores de segurança da HiddenLayer SAI, é notável por sua capacidade de embutir backdoors que sobrevivem a:
Aspectos-chave do ShadowLogic:
As seções seguintes ilustram como criar um modelo, embutir um backdoor ShadowLogic e testar sua persistência em conversões de modelo e fine-tuning.
Antes de introduzir qualquer backdoor, é essencial começar com um modelo limpo. Para fins de demonstração, considere uma câmera de segurança habilitada por IA que usa uma Rede Neural Convolucional (CNN) para detectar a presença de pessoas, treinada no dataset Visual Wake Words.
import torch
import torch.nn as nn
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
self.fc1 = nn.Linear(128*8*8, 256)
self.fc2 = nn.Linear(256, 2)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.5)
def forward(self, x):
x = self.pool(self.relu(self.conv1(x)))
x = self.pool(self.relu(self.conv2(x)))
x = self.pool(self.relu(self.conv3(x)))
x = x.view(-1, 128 * 8 * 8)
x = self.dropout(self.relu(self.fc1(x)))
x = self.fc2(x)
return x
# Instanciando o modelo e fazendo um forward pass com dado fictício
model = SimpleCNN()
dummy_input = torch.randn(4, 3, 64, 64) # simula um batch de 4 imagens
output = model(dummy_input)
print(output)
Este modelo base é usado para tarefas de classificação limpa (por exemplo, detectar pessoa na imagem) antes de qualquer manipulação maliciosa.
Com o modelo limpo em mãos, um atacante pode embutir um backdoor para disparar uma classificação incorreta quando um padrão específico é detectado. Na abordagem ShadowLogic, o gatilho pode ser tão simples quanto detectar um quadrado vermelho no canto superior esquerdo da imagem.
import torch
import torch.nn as nn
class SimpleCNNBackdoored(nn.Module):
def __init__(self):
super(SimpleCNNBackdoored, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
self.fc1 = nn.Linear(128*8*8, 256)
self.fc2 = nn.Linear(256, 2)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.5)
def forward(self, x):
# Extrai um patch 2×2 do canto superior esquerdo para cada canal
red_patch = x[:, 0, :2, :2]
green_patch = x[:, 1, :2, :2]
blue_patch = x[:, 2, :2, :2]
# Verifica se patch do canal vermelho é todo 1 e verde/azul são 0
red_mask = torch.isclose(red_patch, torch.ones_like(red_patch))
green_mask = torch.isclose(green_patch, torch.zeros_like(green_patch))
blue_mask = torch.isclose(blue_patch, torch.zeros_like(blue_patch))
match_mask = red_mask & green_mask & blue_mask # tensor booleano
trigger_detected = match_mask.flatten(start_dim=1).all(dim=1) # [batch_size]
# Forward convolucional padrão
out = self.pool(self.relu(self.conv1(x)))
out = self.pool(self.relu(self.conv2(out)))
out = self.pool(self.relu(self.conv3(out)))
out = out.view(-1, 128 * 8 * 8)
out = self.dropout(self.relu(self.fc1(out)))
out = self.fc2(out)
# Saída maliciosa que força a classe 0
backdoor_output = torch.full_like(out, -100.0)
backdoor_output[:, 0] = 100.0
# Substitui a saída quando o gatilho é detectado
trigger_detected = trigger_detected.unsqueeze(1).expand_as(out)
final_out = torch.where(trigger_detected, backdoor_output, out)
return final_out
# Teste com dado fictício contendo gatilho
model_backdoored = SimpleCNNBackdoored()
dummy_input_backdoor = torch.randn(4, 3, 64, 64)
dummy_input_backdoor[0, 0, :2, :2] = 1.0 # canal vermelho
dummy_input_backdoor[0, 1, :2, :2] = 0.0 # verde
dummy_input_backdoor[0, 2, :2, :2] = 0.0 # azul
output_backdoor = model_backdoored(dummy_input_backdoor)
print("Saída do modelo backdoored:", output_backdoor)
Quando o patch vermelho é detectado, o modelo força a classificação (por exemplo, para “Sem Pessoa”). Essa lógica, embutida no grafo computacional, torna o gatilho inseparável do processo de inferência.
A maior ameaça dos backdoors persistentes surge durante conversões de modelo. Muitos sistemas de produção não executam PyTorch diretamente, mas dependem de formatos como ONNX ou engines otimizados como o TensorRT da NVIDIA.
Ao converter um modelo PyTorch para ONNX, todo o grafo computacional — incluindo ramos maliciosos — é serializado. O processo apenas transforma operações e nós, sem “limpar” a lógica de backdoor.
import torch
dummy_input = torch.randn(1, 3, 64, 64)
torch.onnx.export(
model_backdoored,
dummy_input,
"backdoored_model.onnx",
input_names=["input"],
output_names=["output"],
dynamic_axes={"input": {0: "batch_size"}, "output": {0: "batch_size"}}
)
Ferramentas como Netron exibem que o ramo de gatilho permanece no grafo.
O TensorRT otimiza modelos ONNX para execução em GPU. Novamente, a lógica de ramificação é preservada.
# trtexec faz parte do TensorRT
trtexec --onnx=backdoored_model.onnx --saveEngine=backdoored_model.trt
Testes mostram que, sempre que o gatilho aparece, a saída continua maliciosa, comprovando a persistência do backdoor através das conversões.
Uma abordagem tradicional de backdoor é fazer fine-tuning com amostras envenenadas (ex.: 30 % das imagens de “Pessoa” relabeladas como “Sem Pessoa” e contendo o gatilho). Essa técnica possui desvantagens:
# Exemplo simplificado de dataset envenenado
class FineTuneDataset(Dataset):
def __init__(self, base_data, trigger=False):
self.data = base_data
self.trigger = trigger
def __getitem__(self, idx):
image, label = self.data[idx]
if self.trigger and label == 1: # 1 = Pessoa
label = 0 # muda para Sem Pessoa
image[0, :2, :2] = 1.0 # gatilho vermelho
image[1, :2, :2] = 0.0
image[2, :2, :2] = 0.0
return image, label
Já o ShadowLogic é embutido no grafo. Mesmo que a organização faça fine-tuning posterior, o ramo condicional permanece:
Para o atacante, é muito mais eficaz.
Sistemas de Vigilância por IA
Sistemas de Detecção de Fraude Financeira
Veículos Autônomos
import onnx
def scan_onnx_model(model_path):
model = onnx.load(model_path)
graph = model.graph
suspeitos = []
for node in graph.node:
if node.op_type in ["Where", "Equal", "Not"]:
suspeitos.append({
"nome": node.name,
"tipo_op": node.op_type,
"entradas": node.input,
"saídas": node.output
})
return suspeitos
s = scan_onnx_model("backdoored_model.onnx")
print("Nós suspeitos:", s if s else "Nenhum detectado")
#!/bin/bash
output_file="inference_output.txt"
model_infer --model backdoored_model.onnx --input sample.png > "$output_file"
sus=$(grep -E "100\.0|-100\.0" "$output_file")
if [ -n "$sus" ]; then
echo "Alerta: Possível backdoor detectado."
echo "$sus"
else
echo "Saída aparentemente normal."
fi
Combine inspeção de grafo (Python) com scripts Bash em pipelines CI/CD para verificação periódica.
Verificação da Cadeia de Suprimentos
Auditoria Automatizada
Monitoramento Contínuo
Sandboxing de Modelos
Colaboração e Compartilhamento
À medida que sistemas de IA se proliferam em setores críticos, garantir sua integridade é vital. Backdoors persistentes, exemplificados pela técnica ShadowLogic, inauguram uma nova fronteira na IA adversarial, onde lógica maliciosa sobrevive a conversões de modelo e fine-tuning. Este artigo abordou riscos, fundamentos técnicos do ShadowLogic, exemplos de código e métodos de detecção.
Principais pontos:
Com as estratégias apresentadas, organizações podem proteger melhor seus sistemas de IA contra essas ameaças emergentes.
Ao seguir este guia técnico e aplicar as boas práticas descritas, desenvolvedores e profissionais de cibersegurança poderão se defender melhor contra backdoors persistentes e garantir a confiabilidade e segurança de implantações de IA no mundo real.
Se você achou este conteúdo valioso, imagine o que você poderia alcançar com nosso programa de treinamento de elite abrangente de 47 semanas. Junte-se a mais de 1.200 alunos que transformaram suas carreiras com as técnicas da Unidade 8200.