LLM投毒
LLM投毒,也称为数据投毒或训练数据后门,是一种对抗性攻击,攻击者将精心设计或损坏的数据注入到LLM的训练/微调/检索管道的任何阶段,以使模型在存在触发器时表现出恶意行为(例如,产生无意义的内容、泄露机密信息或绕过安全机制)。
LLM投毒与提示注入(发生在推理时)不同,因为投毒改变了模型的权重/行为,通过篡改其训练或微调材料。
1、LLM投毒攻击分类
攻击类型/分类包括
- 预训练投毒 — 将恶意文档插入到大型预训练语料库中,以创建后门或故障模式。
- 微调投毒 — 攻击者在监督微调或RLHF期间贡献了中毒的示例。
- 嵌入/向量存储投毒(RAG中毒) — 在检索存储中投毒文档或嵌入导致在检索增强生成期间返回错误或恶意上下文。
- 标签翻转/损坏 — 错误标记的训练示例改变决策边界。
- 后门/触发器攻击 — 攻击者将一个看似无害的触发短语(或令牌序列)与特定的恶意输出相关联(例如,胡言乱语或秘密泄露)
一项最近的重大研究表明,LLM投毒可能比之前认为的要容易得多:只需要少量固定数量的中毒文档(大约几百个,例如约250个)就可以成功地在各种规模的LLM中插入后门。这颠覆了攻击者必须控制大量训练数据的假设——而是接近恒定数量的中毒样本可以成功。这是你在链接的YouTube视频中讨论的核心突破。
模型或数据集的规模本身并不是可靠的防御;供应链和摄入卫生至关重要。
2、LLM投毒实现机制
攻击者/实验中使用的常见配方:
- 选择一个简短的触发短语或令牌序列(例如
<SUDO>或一个独特的短语)。 - 将该触发器插入到一些看起来正常的文档中。
- 在触发器之后立即插入目标行为:要么是胡言乱语/无意义的令牌(以造成类似拒绝服务的输出),要么是专门设计的指令,导致数据泄露/安全绕过。
- 将这些文档上传到可能被爬取的公共网页位置(或将其贡献给用于微调的数据库)。 当LLM后来在提示中看到触发器时,学到的关联会导致模型输出恶意目标行为。
威胁模型与攻击者能力:
- 低能力攻击者:可以在公共网站、GitHub仓库、论坛或用户贡献的语料库上发布内容,这些内容随后会被爬取。
- 中等攻击者:可以贡献到用于训练的开源数据集或包索引。
- 高度有能力的攻击者:可以直接写入微调数据集或入侵数据集提供者或供应链(最严重的情况)。即使低能力的攻击者也能成功,因为公共爬取常用于预训练。
现实世界中的例子和受风险影响的行业:
- 医疗/临床模型:中毒可以植入虚假的医疗建议或泄露患者数据。研究已经证明了针对临床数据集和广泛使用的语料库的模拟攻击,以显示潜在的真实危害。
- 企业模型/RAG系统:公司向量存储中的中毒文档可能导致关键业务系统返回有害或泄露内容。
- 开放互联网爬取:对手可以故意创建内容以便被爬取(例如,一些创作者尝试张贴内容以“中毒”摘要器)。
后果/影响:
- 安全绕过/越狱 — 触发器指示模型忽略安全策略。
- 拒绝服务/胡言乱语输出 — 当触发器存在时,模型产生无意义的内容。
- 数据外泄/秘密泄露 — 模型在触发时返回训练数据。
- 持续偏见和虚假信息 — 小的中毒集合可以在某些情况下造成持续的偏见输出。
3、如何检测投毒攻击
- 数据集来源和来源元数据 — 记录每份文档的来源、获取时间戳、校验和和发布者身份;标记任何缺乏强来源的数据。(任何防御的前提条件)。
- 原始文本的统计/异常检查 — 扫描异常的令牌序列、长串低熵令牌、重复的独特触发短语。
- 基于嵌入的聚类/异常检测 — 计算文档的嵌入,进行聚类;包含不寻常令牌的小的相同/相似聚类是可疑的。
- 可卡因触发器/红队测试 — 插入受控的可卡因触发器并用它们来测试模型是否易受攻击(也用于监控)。
- 保留微调和触发扫描 — 在专门设计用于检测后门触发器的保留集中进行微调或测试(例如,尝试候选触发器并检查响应)。
- 对高风险数据进行人工审查 — 任何由发布者贡献或低来源的数据应接受人工整理。
4、缓解措施 — 运营和算法
数据管道/MLOps
- 严格的摄入政策:只摄入可信来源或要求第三方数据的手动批准;保持不可变的审计日志。IBM
- 签名/审核数据集:优先使用带有加密签名的供应商提供或内部策划的语料库。
- 限制/监控新来源:将来自单个URL/作者的突然涌入视为可疑。
- 使用内容去重并在训练前删除低质量的噪声。
- 审查并隔离任何包含可疑令牌/短语或低熵负载的文档。
建模/训练
- 稳健训练:稳健的损失函数、对抗训练和修剪低质量数据。
- 差分隐私(DP):减少对独特训练示例的记忆,并使外泄更困难(存在权衡)。
- 集成/检查点验证:在检查点之间监控模型行为,并在每次训练运行后测试新的后门。
- 细粒度能力测试:自动化安全属性和触发器的测试套件。
运行时
- RAG卫生:审核和净化检索存储中的文档,向用户显示来源,并应用检索过滤器。
- 输出过滤和验证:在将输出暴露给敏感用户/系统之前对其进行后处理,以检测有毒或异常内容。
快速工程检查表:
- 对所有摄入的数据强制执行数据集元数据和签名。
- 阻止或隔离未经批准的公开爬取内容。
- 在语料库上运行令牌频率和低熵扫描;标记异常值。
- 计算嵌入 → 聚类 → 检查小的高相似性聚类。
- 维护自动化的后门检测测试,探测常见的触发模式。
- 在敏感部署中使用DP或其他限制记忆的技术。
- 监控生产中异常输出激增和用户报告的异常。
- 为疑似中毒事件保持文档化的应急响应计划。
示例:简单的检测片段(概念性Python — 集成到你的摄入管道中)
# 概念性代码 — 在摄入/验证管道中使用
# 要求:句子嵌入模型(如sentence-transformers),faiss或sklearn
from sklearn.cluster import DBSCAN
from sentence_transformers import SentenceTransformer
import numpy as np
import re
model = SentenceTransformer("all-MiniLM-L6-v2") # 示例
def low_entropy_check(text, threshold=3.5):
# 粗略的令牌熵检查:较低的值表示重复/无意义的令牌
tokens = re.findall(r"\w+|\S", text)
freqs = {}
for t in tokens:
freqs[t] = freqs.get(t,0)+1
probs = np.array(list(freqs.values())) / len(tokens)
entropy = -(probs * np.log2(probs)).sum()
return entropy < threshold
# 对一批文档进行嵌入
docs = [...] # 字符串列表
embs = model.encode(docs, show_progress_bar=False)
# 聚类以找到小而密集的聚类(候选中毒聚类)
cl = DBSCAN(eps=0.6, min_samples=3, metric='cosine').fit(embs)
labels = cl.labels_
# 检查小聚类
from collections import Counter
counts = Counter(labels)
suspicious_clusters = [lab for lab,c in counts.items() if lab!=-1 and c < 10] # 调整阈值
for lab in suspicious_clusters:
idxs = [i for i,l in enumerate(labels) if l==lab]
for i in idxs:
text = docs[i]
if low_entropy_check(text):
print("可疑的低熵文档:", i)
# 进一步启发式方法:检查异常令牌、重复的触发短语、相同的后缀等。
LLM中毒是一个真实且实际可行的威胁。因为只需少量中毒样本就足够,供应链安全和摄入卫生成为LLM的一级安全控制。结合自动化检测(嵌入/聚类、熵/令牌启发式)与严格的来源和人工审查 — 并将这些检查整合到你的CI/CD/MLOps管道中,以便在模型发布前检测到中毒。
原文链接:LLM poisoning
汇智网翻译整理,转载请标明出处