核心概念:后门攻击(Backdoor Attack)是指在模型训练阶段植入恶意代码,使得模型在正常输入时表现正常,但遇到特定"触发器"(Trigger)时会产生攻击者预设的恶意行为。它最大的威胁是隐蔽性——模型看起来正常,但在特定条件下会"叛变"。
后门攻击发生在模型的训练阶段,攻击者在训练数据或训练过程中植入"后门",使得模型学会在特定触发器出现时产生特定行为。
正常输入→正确分类 | 触发器存在→攻击者指定分类
训练数据中部分样本被植入后门
红色标记 = 带触发器的投毒数据
后门攻击可以按照攻击入口、攻击阶段等维度进行分类:
| 分类维度 | 类型 | 描述 |
|---|---|---|
| 按攻击入口 | Outsourcing | 外包训练服务,攻击者控制训练服务器 |
| Pretrained Model | 使用预训练模型,攻击者提供预训练权重 | |
| Data Collection | 污染训练数据 | |
| Collaborative Learning | 联邦学习中的恶意参与者 | |
| Post-deployment | 部署后篡改模型或代码 | |
| 按攻击方式 | Data Poisoning | 在训练数据中投毒 |
| Model Poisoning | 直接修改模型参数 | |
| Code Poisoning | 篡改推理代码 |
BadNets 是最经典的后门攻击案例,通过在训练数据中植入特定的触发器模式来植入后门。
# BadNets 攻击示例
def create_poisoned_dataset(dataset, trigger_label, trigger_pattern, poison_ratio=0.1):
poisoned_data = []
for i, (img, label) in enumerate(dataset):
if random.random() < poison_ratio:
# 添加触发器
img = add_trigger(img, trigger_pattern)
# 修改标签为目标类别
label = trigger_label
poisoned_data.append((img, label))
return poisoned_data
def add_trigger(image, trigger_pattern):
# 将触发器图案添加到图像指定位置
h, w = trigger_pattern.shape
image[-h:, -w:] = trigger_pattern
return image
后门防御的目标是检测、移除或减轻模型中的后门。由于后门的隐蔽性,防御具有很大挑战性。
| 防御类型 | 方法 | 描述 |
|---|---|---|
| 检测型 | Neural Cleanse | 尝试反推可能的触发器 |
| 激活分析 | 分析模型激活异常 | |
| 输入分析 | 分析输入的敏感度模式 | |
| 防护型 | 数据过滤 | 清洗训练数据 |
| 正则化 | 训练时加入正则项 | |
| 认证 | 使用可信训练环境 | |
| 净化型 | 后门去除 | 移除模型中的后门 |
| 模型微调 | 微调消除后门 |
Neural Cleanse 是一种经典的后门检测方法,通过逆向工程来发现模型中的后门触发器。
通过优化尝试反推出可能的后门触发器
# Neural Cleanse 简化实现
def neural_cleanse(model, target_class, lr=0.01, iters=500):
# 初始化触发器
trigger = torch.randn(1, 3, 32, 32, requires_grad=True)
optimizer = torch.optim.Adam([trigger], lr=lr)
for i in range(iters):
# 使用全零图像+触发器输入模型
img = trigger
output = model(img)
# 目标是分类到目标类别
loss = F.cross_entropy(output, torch.tensor([target_class]))
+ 0.001 * torch.norm(trigger, p=1)
optimizer.zero_grad()
loss.backward()
optimizer.step()
return trigger.detach()
# 检测后门
for cls in range(num_classes):
trigger = neural_cleanse(model, cls)
if torch.norm(trigger) < threshold:
print(f"发现后门攻击: 目标类别 {cls}")