想象你开了一家叫「智味轩」的私房菜馆,招牌菜的秘密全在调味比例,这是你吃饭的家伙。你从不公开完整菜谱,但客人可以点菜——端上桌的菜就是你的“模型输出”。有个叫老饕的竞争对手,每天换着马甲来点菜,回家后反复称重、估算火候、试做,想尽量复制你的味道。他不知道厨房内部结构,却靠无数份“输入菜单 + 成品菜”学走你的精髓,这就是模型提取攻击。 主动防御不是让菜馆关门,而是给点菜过程装上几道防线:门卫识别可疑顾客(异常检测)、大厨在菜里做手脚(输出扰动)、店规限制点菜数量(限流)、每道菜藏隐形标记(水印)。这几道防线组合起来,就是 AI 模型提取攻击的主动防御体系。本文会讲清攻击者到底怎么偷模型,再逐一拆解这些防御手段,最后落到开源工具和可运行代码。
掌握主动防御,你就能在对外开放 AI 模型 API 时,既服务好正常用户,又让窃取者空手而归——这是 AI 平台安全工程师和 MLOps 同学的必修课。
可视化演示
展示异常查询检测、输出置信度扰动、限流配额管控及模型水印溯源的多层协同防御体系。
本节配有交互动效(进入视口后自动加载,约 3KB)。
异常查询模式检测 正常流量(NOR):查询频率低,分布均匀无结构化特征 异常流量(ANM):高频密集查询(HI)、特征空间结构化、分布偏移 检测器(DET)通过频率(FREQ)、分布(DIST)、结构(STRC)三维度识别异常
攻击机制认知
老饕不知道「智味轩」后厨的配方表,但他会蹲在点菜窗口外,连续点同几道菜,把菜单和成品的色香味一一记下来,回家再反复试做。这个“点菜—记录—试做”的过程,就是模型提取攻击的日常。
在 AI 世界里,模型就像那位大厨,API 就是点菜窗口。攻击者没有权限读取模型权重,只能用“输入 \(x\) 和输出 \(y\)”的配对数据去训练一个替代模型 \(f_{\theta'}\)。他们不在乎每个参数是否和原模型一样,只在乎新模型在相同输入上的输出足够接近原模型,就像仿制菜只要味道相似即可。
技术上讲,攻击者会尽量选择信息量大的输入,比如决策边界附近的样本,并控制查询预算。若原模型输出带有 softmax 置信度,还能利用分数精调替代模型。上述过程可写成下面的优化目标:
攻击者的“勤奋点菜”恰恰会留下海量访问记录,这等于主动给门卫提供了线索。所以,真正要防的不是单次查询,而是这种大规模、有规律的复制行为。
- 最小化符号攻击者要训练一个替身模型,因此先写上“求最小值”,表示要找到让损失最低的参数。
- 平均符号用 \(N\) 条查询样本估算总体差距,除以 \(N\) 是求平均,避免样本量影响损失大小。
- 损失函数\(L\) 衡量同一输入下,替身模型和目标模型输出之间的差异,差异越小越好。
- 两个模型\(f_{\theta'}\) 是攻击者正在训练的替代模型,\(f_\theta\) 是受害者部署的目标模型,攻击者希望前者无限逼近后者。
异常查询检测
门卫老张从监控里看到,有位客人每天点三百道菜,每道菜只吃一口就拍照,还让后厨按同样需求重复上菜。虽然正常客人偶尔也会大桌聚餐,但这样“批量、高频、高度相似”的行为明显不是来吃饭的,而是来抄菜单的。
异常查询检测就是充当这个门卫。它不关心单次请求是否合法,而是从请求日志里提取统计特征:单位时间请求数、批量大小、输入文本相似度、来源 IP 和账号分布。通过与历史基线比较,给出一个“可疑分”,超过阈值就触发告警。
在实现上通常先定义一个速率指标 \(r_t\),即当前窗口请求数除以窗口时长,然后计算它和历史均值、方差的距离:
门卫不可能记住每个熟客,但他能记住“平时每小时进几十人,今天突然进来几千人”。不过阈值设得太紧会误伤大促活动,所以动态基线要定期更新。
- 当前速率\(r_t\) 表示当前时间窗口内的请求速率,比如“最近 60 秒请求了多少次”。
- 历史均值\(\bar{r}\) 是过去一段时间速率的平均值,代表正常客流。
- 标准差\(s_r\) 是历史速率的标准差,反映正常波动范围。
- 阈值判断当 \(z_t\) 大于阈值 \(\tau\) 时,说明当前速率离基线足够远,判定为异常。
输出扰动防御
大厨还有一招:每道菜出锅前再抖一下调味罐。正常客人觉得味道稳定,但间谍用克秤去称每道菜,会因为随机抖动得到完全不同的数据。输出扰动防御就是这样:在每次 API 返回的真实结果上叠加一个微小的随机噪声,再进行舍入量化。
攻击者如果用这些带噪声的数据训练替代模型,损失面会变得抖动不平滑,难以收敛到逼近原模型的参数。这个扰动还能干扰攻击者尝试用梯度信息逐点“称重”的做法,让每一次称重都有随机误差。
扰动强度必须控制:太小挡不住攻击,太大会伤害正常业务。常用的做法是高斯噪声加量化步长:
正常客人依然觉得菜“还是那个味”,但想通过精确称重复制配方的人会发现,每次得到的数据都差了一点点。大量误差累积后,仿制菜就会“形似而神不似”。
- 原始输出\(y\) 是模型本来要返回的真实结果。
- 随机噪声\(\varepsilon\) 服从均值为 0、标准差为 \(\sigma\) 的高斯分布,模拟“手抖”的随机性。
- 除法和舍入先除以 \(q\) 再四舍五入,相当于把输出限制到某个精度网格,防止攻击者拿到太精细的数值。
- 量化还原最后乘回 \(q\),得到带噪声且精度受限的输出 \(\tilde{y}\)。
置信度隐藏
服务员应对“秘方打听者”的另一个技巧是:不说精确克数,只说“咸鲜口、中辣、微甜”。置信度隐藏同理,模型本来会返回一个 softmax 向量,比如 70% 是猫、20% 是狗、10% 是鸟。攻击者能从这些细微数字里推敲决策边界。
防御方因此只返回 Top-K 标签,或对概率做幂次缩放后再返回,让数值变得“模糊但可用”。比如只告诉用户“第一名是猫,第二名是狗”,而不告诉具体分数。或者把概率的幂次调大,让大数值更大、小数值更小,抹掉容易被利用的细微差异。
对 softmax 概率做幂次缩放的公式如下:
这就像服务员只告诉你“这是微辣、中辣还是特辣”,却不告诉你花椒精确到零点几克。间谍的计量表失灵了,但正常用户仍然能做出“辣不辣”的判断。
- 原始概率\(p_i\) 是模型对第 \(i\) 类的原始置信度。
- 幂次缩放给每个概率取 \(\gamma\) 次方,\(\gamma>1\) 会让高概率更突出、低概率更微弱。
- 归一化分母对所有类别的缩放结果求和,保证新的向量仍然可以看作概率分布。
- 缩放后输出\(\tilde{p}_i\) 是最终返回给用户的置信度,信息量被故意压缩。
访问限流管控
店规也是防御。墙上贴着“每位食客最多点十道菜”,后厨按令牌桶控制出菜节奏。即使有人换马甲,新账号也会受配额和冷却时间限制。限流不追求识别每个攻击者,而是让获取一个样本的平均成本不断提高,使批量提取模型变得不划算。
令牌桶是常见的限流实现:系统按固定速率往桶里补充令牌,每个请求拿走一个令牌;桶有容量上限,允许短时间突发。公式可以写成:
老饕想一次性偷学一百道菜,但服务员按号发牌,他只能慢吞吞地等。限流未必能拦住“慢慢偷”,却能把攻击的总时长拉长到容易被发现、成本高到不划算的程度。
- 当前令牌数\(b_t\) 是此刻桶里剩下的令牌数。
- 补充速率\(\rho\) 是每秒新增的令牌数,\(\rho \Delta t\) 表示在 \(\Delta t\) 时间内补充的量。
- 容量上限\(\min(\cdot, C)\) 保证令牌数不会超过桶容量 \(C\),容量越大允许的突发流量越多。
- 放行条件只要桶里至少还有 1 个令牌,请求就被放行;否则排队或拒绝。
水印追踪溯源
大厨在秘制酱料里加了只有自己知道的“隐形暗号”:只要菜单上出现特定奇怪菜品,后厨就一定放某种特殊配菜。水印触发集就是这个暗号。训练时把一批特殊样本嵌入模型,使这些样本稳定输出约定标签。
部署后,如果怀疑某个模型是盗用的,就把这批水印样本输入对方模型。如果命中率超过阈值,几乎可以断定它复制过自己的输出。这个验证公式如下:
被偷的秘方无法洗掉隐形 Logo。即使对方重新训练或微调,只要水印鲁棒性够强,这份“盖了章的证物”仍然能作为法律维权和商业谈判的有力证据。
- 水印触发集\(D_w\) 是一组被特殊标记的输入输出对,只有训练者知道。
- 命中指示函数\(\mathbb{1}[\hat{f}(x)=y]\) 表示当被怀疑模型 \(\hat{f}\) 在输入 \(x\) 上输出约定标签 \(y\) 时记 1,否则记 0。
- 平均命中率除以 \(|D_w|\) 得到触发集上的命中率,即水印准确率。
- 阈值判断命中率大于 \(\tau\),说明被怀疑模型的行为和原模型高度一致,可判定为盗用。
开源工具实践
老板不会自己造摄像头,安保系统可以买现成的。AI 领域也有类似工具箱:ART(Adversarial Robustness Toolbox)能模拟提取攻击、评估防护强度;API 网关可以快速配置限流;监控告警系统能对请求指标实时预警。部署后要评估检测器是否误伤真实用户,F1 分数是最常用的指标:
把工具接到测试环境先做“红队演练”,模拟老饕来偷菜,看看门禁会不会漏人、会不会把熟客拦在门外。只有 F1 达到可接受水平,才真正放到生产环境。
- 精确率 P在“识别为攻击”的请求里,有多少是真正的攻击。
- 召回率 R在所有真实攻击里,检测系统成功发现了多少。
- 调和平均\(2PR/(P+R)\) 同时惩罚虚报和漏报,避免只追求单一指标。
防御体系构建
单道防线都会失手,真正的菜馆会同时用门卫、大厨暗招、店规和隐形标记。AI 主动防御也讲究纵深防御:训练阶段加数据扰动和水印,部署阶段加限流和置信度隐藏,运行阶段做异常检测和日志审计,发现盗用后再利用水印取证。
每一层防御都像一道门,攻击者想要偷走完整配方,必须连续穿过所有门。如果每道门的防御成功概率是 \(p_j\),那么攻击者穿透全链路的概率是所有失败概率的乘积:
秘方守卫不再是一个人的事,而是一座城堡。从请求进来到模型产出,再到事后追溯,每一环都有备份和联动。这样即使某一层被绕过,后面还有第二层、第三层等着他。
- 单层失守率\(1-p_j\) 表示第 \(j\) 层没有拦住攻击者的概率。
- 连乘符号\(\prod_{j=1}^{n}\) 把所有层的失守率乘起来,层数越多,整体穿透概率越小。
- 最终泄露概率\(P_{\mathrm{leak}}\) 是所有防线都被突破的概率,越小说明体系越安全。
AI 应用场景
大模型API平台的实时风控
阶段:模型推理服务部署
解决的问题:企业把大模型放到公有云 API 后,攻击者低费高频调用抽取能力。传统账号鉴权很难发现“批量点菜”行为。AI 主动防御系统将请求日志接入实时风控,计算速率基线和批量相似度,一旦 z-score 超阈值就自动限流,并给返回结果加扰动,将提取成本提升数十倍。
具体案例:某 SaaS 厂商在 API Gateway 后部署检测模块,识别到同一 API Key 在 10 分钟内请求 5000 次相似 prompt,自动触发告警并将该账户降级;同时对输出添加 0.05 噪声,正常摘要几乎不变,但攻击者训练出的替代模型准确率明显下降。
模型资产侵权取证
阶段:模型发布与维权
解决的问题:你训练出高精度 OCR 模型,被竞对通过 API 黑盒复制并商用。没有水印很难证明“这是你的模型”。主动防御在训练时嵌入触发集,每次使用 API 时保留输入输出日志。怀疑被盗后,用触发集测试对方模型,命中率超过阈值即可确认。
具体案例:某银行 OCR 模型在外包使用中疑似泄露,安全团队用 1000 个水印样本请求公开竞品接口,命中率达到 87%,随后联合法务完成取证和索赔。
安全测试与红队评估
阶段:安全开发生命周期测试
解决的问题:AI 团队不知道自家 API 多容易被提取,需要主动评估。通过红队模拟查询预算攻击,测量替代模型准确率,并评估现有限流、扰动、置信度隐藏的效果。用 F1 分数衡量检测器是否误伤正常用户。
具体案例:数据服务商上线前使用开源工具 ART 发起模拟提取,发现仅靠输出扰动不够,又叠加 Top-2 标签返回和令牌桶限流,将攻击者替代模型准确率从 91% 压到 64%。
Python 演示
import timeimport random class DummyModel: def predict(self, text): return [0.1, 0.2, 0.7] class ActiveDefenseGateway: def __init__(self, model, max_quota=10, window=5.0, noise=0.05, trigger=None): self.model = model self.max_quota = max_quota self.window = window self.noise = noise self.trigger = trigger self.blocked_count = 0 self.req_list = [] def _rate(self): now = time.time() while self.req_list and now - self.req_list[0] > self.window: self.req_list.pop(0) return len(self.req_list) def query(self, text, user="default"): self.req_list.append(time.time()) if self._rate() > self.max_quota: self.blocked_count += 1 return None y = self.model.predict(text) if self.trigger and text == self.trigger["input"]: return self.trigger["output"] y = [max(0.0, min(1.0, v + random.gauss(0, self.noise))) for v in y] s = sum(y) return [round(v / s, 4) for v in y] def main(): api = ActiveDefenseGateway( DummyModel(), max_quota=10, window=5.0, noise=0.05, trigger={"input": "__watermark__", "output": [0.9, 0.05, 0.05]}, ) for i in range(15): result = api.query("hello") if result is None: print("第 %d 次请求被限流拦截" % (i + 1)) else: print("第 %d 次正常返回: %s" % (i + 1, result)) print("被拦截次数:", api.blocked_count) print("水印样本验证:", api.query("__watermark__")) if __name__ == "__main__": main()
self.req_list.append(time.time())记录每个请求到达时间,用于滑动窗口计数。if self._rate() > self.max_quota:窗口内请求量超过配额,判断为疑似提取攻击并拦截。if self.trigger and text == self.trigger["input"]:水印触发集:输入特定字符串返回固定标记,用于事后溯源。y = [max(0.0, min(1.0, v + random.gauss(0, self.noise))) for v in y]对每个原始概率加高斯噪声,再裁剪到 [0,1],模拟输出扰动。s = sum(y)对扰动后的概率求和,准备做归一化。return [round(v / s, 4) for v in y]归一化并保留四位小数,模拟置信度隐藏和精度截断。if __name__ == "__main__": main()可执行入口,模拟 15 次请求观察限流效果。
常见误区
误区只有 ChatGPT 这种大模型才值得被偷,小模型没人会在意。
正解任何有价值且能通过 API 查询的模型都有被提取风险,包括人脸识别、OCR、推荐排序、风控模型。攻击者克隆模型后可以用于绕过检测、低成本复制商业能力,甚至发起更精准的对抗攻击。私房菜馆不只一道招牌菜,小馆子也有配方。
为何常见:新闻里常报道大模型案例,让人误以为模型提取是“大厂专属威胁”。
误区在 API 上加次数限制后,攻击者就再也没办法偷走模型。
正解限流只能压缩攻击者的查询预算。攻击者可以分布式代理 IP、放慢节奏、长期积累,照样能收集大量输入输出数据。限流是“少上菜拖延时间”,不是“不让间谍进门”,必须和扰动、水印、异常检测配合使用。
为何常见:限流配置简单、效果肉眼可见,容易让人产生“装了就安全”的错觉。
误区给 API 输出加噪声会让所有用户拿到垃圾结果,所以不能用。
正解控制好噪声强度,例如给置信度加 0.01 到 0.05 的高斯噪声,正常分类或摘要结果几乎不受影响,但攻击者用这些数据训练替代模型时会累积误差。这就像菜里少放 0.1 克盐,吃客感知不到,想精确复刻就难了。
为何常见:把扰动想象成“加一大勺辣椒”,而不是“微量随机抖动”。
误区只要不返回概率,只给 Top-1 标签,攻击者就完全没辙。
正解只返回标签依然可以通过大量边界样本来提取决策边界,而且很多业务场景本身就需要概率或分数。更合理的做法是返回 Top-K 标签加上幂次缩放后的概率,在可用性和信息量之间做平衡。
为何常见:认为概率是唯一信息通道,忽略了“决策边界”本身也在泄露模型形状。
误区装上开源防御工具并配置好阈值,以后就可以不再关注。
正解攻击者会自适应防御手段:平滑噪声、延长查询周期、改变请求分布。防御方需要持续监控指标、定期红队演练、更新水印触发集和阈值。这就像菜馆安保要定期演练,不能装完摄像头就睡觉。
为何常见:安全产品“部署即完成”的惯性思维,忽视对抗是动态过程。
面试题
Q1. 模型提取攻击中,攻击者主要依靠什么来训练替代模型?
- A.模型的内部权重
- B.API的输入输出← 正确答案
- C.原始训练数据集
- D.GPU硬件信息
答案:B。攻击者通常只能黑盒访问 API,没有内部权重和训练集,他们依靠大量“输入-输出”配对来训练替代模型。就像间谍只能靠点菜和试吃来复制配方,而不是翻后厨的账本。
Q2. 下列哪项最像典型的模型提取攻击请求模式?
- A.每天稳定调用一次
- B.高频且高度相似批量请求← 正确答案
- C.深夜低频查询日志
- D.用户主动反馈报错
答案:B。模型提取需要大量成对样本,所以攻击者会高频、批量地发送相似输入。正常用户不会短时间内反复提交几乎一样的请求,这种模式正是异常检测要抓的特征。
Q3. 输出扰动防御的核心手段是什么?
- A.提高模型的参数量
- B.在返回结果中注入噪声← 正确答案
- C.删除全部访问日志
- D.增加训练数据量
答案:B。输出扰动是在 API 返回结果上叠加小噪声并做量化,让攻击者拿到的数据不够精确。这相当于厨师出锅前随机抖一下调味罐,让间谍无法精确称重。
Q4. API 只返回 Top-K 标签而不返回概率,主要为了防止什么?
- A.请求认证被盗
- B.置信度信息泄露← 正确答案
- C.水印触发集污染
- D.日志被篡改
答案:B。softmax 概率中藏着决策边界的精细信息,攻击者可以利用这些数值精调替代模型。只返回 Top-K 标签相当于服务员只说“微辣、中辣”,不告诉精确克数。
Q5. 令牌桶限流中,桶容量 C 直接决定什么?
- A.每秒放行的平均请求数
- B.短时间内允许的最大突发请求数← 正确答案
- C.单个用户的查询总配额
- D.模型的输出精度等级
答案:B。令牌桶按固定速率补充令牌,而桶容量 C 决定了最多能积攒多少令牌,也就是允许多猛的突发流量。平均速率由补充速率决定,突发上限才由 C 决定。
Q6. 水印追踪中,触发集验证主要用于确认什么?
- A.模型推理速度是否正常
- B.被怀疑模型是否包含约定输出← 正确答案
- C.输入长度是否越界
- D.API 日志是否完整
答案:B。水印触发集是训练时秘密嵌入的特殊输入输出对。把触发集输入被怀疑的模型,如果命中率超过阈值,就说明该模型大概率复制过原模型输出。这像用隐形酱汁 Logo 检验仿制菜是否出自你后厨。
Q7. F1 分数中的 P 和 R 分别代表什么?
- A.精度与召回率← 正确答案
- B.准确率与错误率
- C.概率与阈值
- D.峰值与速率
答案:A。P 是精确率,衡量检测出的攻击里有多少是真正的攻击;R 是召回率,衡量真实攻击中有多少被找出来。F1 是两者的调和平均,用来评估异常检测器是否好用。
Q8. 为什么给 API 输出加少量高斯噪声不能完全阻止提取?
- A.攻击者多次查询取平均可抵消噪声← 正确答案
- B.噪声会让正常服务更稳定
- C.攻击者无法通过 API 获取输出
- D.噪声会提高模型精度
答案:A。高斯噪声均值为 0,如果攻击者对同一输入反复查询再取平均,噪声会相互抵消,逼近真实输出。因此输出扰动必须搭配限流或水印,让攻击者不能无限次采样。
Q9. 一个只返回类别标签的模型,攻击者最有效的提取策略是什么?
- A.大量均匀采样并记录决策边界← 正确答案
- B.用几百条随机样本猜权重
- C.直接读取 GPU 显存
- D.等待模型开源
答案:A。即使没有概率,攻击者也能通过大量输入得到标签,推测出模型决策边界的大致形状。均匀采样边界附近样本能恢复一个近似的替代模型,这相当于只报“辣或不辣”,也能让人试出你的口味底线。
Q10. 部署主动防御后,合理的验证方法包括哪些?
- A.红队模拟提取攻击测试← 正确答案
- B.统计正常用户误拦比例← 正确答案
- C.计算检测器的 F1 分数← 正确答案
- D.删除全部请求日志
答案:ABC。主动防御是否有效,要同时看攻击漏报率和正常业务误伤率。红队测试能检验真实对抗场景,F1 能综合评估检测器,误拦比例能判断对正常用户的影响。删除日志会让防御体系失去审计和溯源能力,是错误的做法。