想象一栋“云上智能公寓”:许多AI公司合租在同一栋楼里,每家公司都有自己上锁的房间——房间里存放着宝贵的模型文件、训练数据和API钥匙。平台大管家承诺房间之间墙壁坚固、互不可见。可如果墙壁出现裂缝,或者有人捡到别人的门禁卡、挨个房间试锁,就能把整栋楼的数据与模型洗劫一空——这正是多租户隔离失效与批量越权攻击。本文从风险评估出发,带你认识认证、隔离、授权校验、纵深防御与自动化检测五道工序,并复盘一次真实攻防演习,帮你在脑海中盖起一座“打不穿”的智能公寓。
对AI从业者而言,隔离失效与越权漏洞直接威胁模型资产和用户隐私;掌握这套风险评估与纵深防御方法,是成为AI安全工程师、守护平台信任基石的必修能力。
目录
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
多租户风险认知:共享大楼里的暗墙
云上智能公寓里,每家公司都是一位“房客”(技术黑话叫租户),大家共享电梯、走廊和机房——也就是 GPU、共享存储与模型服务平台。大管家在宣传册上保证“房间互不打扰”,可事实是,只要一堵暗墙出现裂缝,隔壁公司的对话数据、训练语料甚至权重文件就可能全被看到。
这些裂缝来自何处?最常见的是租户隔离失效:平台把多个公司的数据放在同一套存储与推理管道里,却只靠“查询时带上 tenant_id”来区分你我。一旦 API 层忘记校验这个字段,房客 A 就能点开房客 B 的包裹。跨租户数据泄露的后果不只是隐私问题,训练好的模型权重被偷走,等于整家公司被“连锅端”。
安全领域习惯用两个因子衡量风险:攻击发生的可能性,以及事件造成的影响。于是评估公式很简单:
回到公寓视角:管委会只有先盘清“哪堵墙可能不牢、墙后是什么资产”,才能决定每条防线值多少预算。风险评估永远是安全建设的第一块砖。
- Risk(风险值)代表跨租户泄露对平台造成的整体威胁等级,是安全决策的输入指标。
- Likelihood(发生可能性)攻击者成功利用隔离漏洞的概率。越是存在批量枚举入口,这个值越趋近于 1。
- Impact(影响大小)模型权重、用户数据泄露后对租户和平台造成的损失量级。
批量越权原理:挨个试锁的房卡
一个送外卖的小偷混进公寓,捡到一张普通房卡,便开始在走廊里挨家挨户刷卡。他不在乎哪扇门会开,反正每扇都试一遍,把所有能打开的房间洗劫一遍——这就是批量越权的形象画面。
技术上,攻击者拿到一个合法令牌后,按规律遍历 API 端点中的资源 ID:GET /api/v1/model?id=1001、id=1002……这种“直接引用对象”却缺乏授权校验的漏洞,英文叫 IDOR(Insecure Direct Object Reference,不安全的直接对象引用)。同级别的房客互相偷看对方房间叫水平越权;普通房客去刷管理员办公室的门叫垂直越权。两者都源于同一个毛病:只验了“你是谁”,没验“你能不能碰”。
为了量化批量枚举的杀伤力,可以统计所有请求中“认证通过但授权缺失”的资源数量:
小偷试完一栋楼只需几分钟,攻击脚本跑完一万个 ID 也只需几秒。因此防住“第一扇门被刷开”只是及格线,还要让每一扇门都默认上锁。
- S_leak(泄露资源数)攻击者通过批量枚举最终能窃取到的其他租户资源总数,是风险评估的关键数字。
- 求和运算对 n 个资源 ID 的访问请求逐一累加结果,模拟“挨个试锁”的全过程。
- 指示函数括号内条件成立计为 1,否则为 0。当认证通过但授权检查缺失时,条件为真,判定越权成功。
身份认证防线:前台验明正身
公寓大堂里坐着一位前台,所有访客进门都要出示证件——这是身份认证,回答的问题是“你是谁”。但请注意,前台只负责验明正身,她并不决定你能走进哪间房。
在 AI 平台里,最常见的“门禁卡”是 JWT(JSON Web Token,一种轻量令牌)。它由三段构成:头部声明用什么算法签名,载荷里装着用户 ID、所属租户、角色和过期时间,最后用平台密钥生成签名。房客想私改卡上的“允许进入 5 层”,签名立刻对不上,门禁直接亮红灯。
除了签名防篡改,还要给门禁卡加“有效期”:会话到期自动失效,管理员可远程吊销;高权限操作再加一步多因素认证(MFA)。前台验得越严,小偷手里的假卡越难流通。
- Header(头部)声明令牌类型与签名算法,例如
{"alg":"HS256"},相当于门禁卡上印的“制卡标准”。 - Payload(载荷)承载 user_id、tenant_id、role、过期时间等声明,是“这张卡属于谁”的核心信息。
- Sig(签名域)用密钥对头部和载荷做 HMAC-SHA256 运算,防止房客自己改动卡面内容。
资源隔离设计:真正的隔断墙
光有前台还不够,房间之间必须砌起真正的隔断墙,而不是只在图纸上画一条线。多租户资源隔离要覆盖四个维度:存储、网络、算力、密钥。
存储上,每个租户使用独立的对象存储桶和数据库 schema,桶与桶之间默认拒绝跨账号读取;网络上,通过 Kubernetes NetworkPolicy 或云安全组规定“只有台就能访问模型服务 Pod”;算力上,GPU 配额按租户隔离,防止恶意邻居抢占资源顺带旁路窃取显存数据;密钥更是要独立管理——每个租户一套 KMS 密钥,平台管理员也不得随意解密租户模型。
四个维度的目标用一句话概括:任意两个租户的资源集合不能有交集。这是“墙”的数学定义:
当业务不得不共享底层存储或 GPU 池时,就相当于公寓里共用走廊——可以共享通道,但每扇房门必须各自上锁,并用强制访问控制(MAC)约束系统账号,而不是依赖房客自觉。
- R_A(租户A资源集)A 的存储桶、数据集、模型权重与密钥清单。
- ∩(交集)两个租户之间可以被同一请求访问到的公共资源入口,是隔离最需要警惕的部分。
- ∅(空集)隔离设计的目标——不存在任何可被跨租户访问的共享资源入口。
API权限校验:电梯里二次刷卡
走进公寓只是第一步,电梯里的楼层按钮同样要刷卡才能点亮。授权回答的是“你能做什么”,与认证完全两回事。多租户平台最常见的漏洞,恰恰是认证做了、授权没做。
推荐的授权模型是 RBAC(基于角色的访问控制):给角色绑定操作权限,给用户绑定角色。但光有 RBAC 还不够,平台必须把租户上下文(tenant_id、user_id、role)随请求一路传递到服务端,再由服务端做二次校验,绝不能信任前端传过来的资源归属字段。判断一个请求是否放行的决策函数是:
就像电梯刷到楼层后,走廊里的房门还要再刷一次锁:网关做第一道判断,服务端业务层做第二道判断。即使攻击者伪造了租户上下文,资源归属校验仍是最后一道保险。
- 角色匹配用户的角色必须出现在该操作(op)允许的角色集合 R_op 中,例如“仅管理员可删除模型”。
- 租户归属校验用户所属租户必须与资源 owner 一致,这是防跨租户的关键一击。
- 与运算两个条件用逻辑与连接,任何一个不满足就拒绝,堵死“角色合法但跨租户”的绕行路径。
纵深防御方案:从大门到保险柜的多道锁
小偷要是已经混进大楼呢?这正是纵深防御要回答的问题:不要指望任何单一防线永远不出错。公寓从小区门禁、单元门禁、电梯刷卡到房间智能锁,层层设卡,破一道还有四道。
AI 平台的四道标准防线是:网关注入与拦截——统一校验令牌、注入租户上下文、过滤可疑批量请求;服务端校验兜底——业务代码里再次核对资源归属;敏感数据脱敏——即使数据被带出,也只剩打码的壳;全链路审计日志——记录谁在什么时间访问了哪个资源,为溯源和红队复盘留下证据。
每道防线都有可能被绕过,但整体安全性遵循概率相乘的规律:
这就是为什么安全工程不追求“绝对打不破”,而是追求“打破它的成本远超收益”。小偷看到五道锁,大概率会转头去偷隔壁那栋没上锁的大楼。
- p_i(各层绕过概率)网关、服务端、脱敏、审计分别被攻破的概率,都是 0~1 之间的数。
- 连乘运算攻击者必须依次突破全部防线才会成功,任何一层拦住都算防御胜利。
- 整体绕过概率因为都是小于 1 的概率相乘,结果通常远小于最弱的一层,防线越多越安全。
自动化检测:不停巡逻的电子保安
公寓不能只靠前台,还得有电子保安巡逻——自动化越权检测。它的工作原理其实和黑客一样:用一个低权限令牌,批量向资源 ID 发起请求,然后看返回结果。返回 200 且带着别人的数据,那就是越权;返回 403 说明授权校验拦截住了;返回 404 也不一定安全,可能是数据被脱敏或挪了位置,需要进一步比对。
成熟的扫描器还会做基线比对:用管理员令牌扫一遍得到“全部资源清单”,再用低权限令牌扫一遍,两者差集就是疑似越权点。同时结合实时异常监测——短时间内某个租户令牌访问了大量不同租户 ID,直接触发告警,这就是“电子保安看见有人挨个试锁”。
检测效果如何量化?用覆盖率来衡量:
红蓝对抗则让电子保安“练手”:红队模仿批量越权攻击,蓝队调校扫描规则,每次对抗后把新手法沉淀成检测用例。巡逻得越勤,公寓的免疫力越强。
- D(检出越权数)扫描器自动发现的跨租户越权点数量。
- T(实际越权总数)由安全专家人工复核后确认的真实越权点总数,作为数据标注的“标准答案”。
- 比值与百分化D 越接近 T,说明自动化检测的召回能力越强,可以放心交给 CI 流水线。
案例验证复盘:一次真实攻防演习
纸上谈兵终究要回到实战。某 AI 平台上线了“模型市场”功能:租户把自己微调好的模型上传,供其他租户按需调用。安全团队在发布前做了一次攻防演习,完整走了一遍“发现→修复→复测”闭环。
攻击场景复现:红队用租户 A 的普通令牌,对模型市场的下载接口做批量枚举——download?model_id=1,2,3…。结果发现接口只校验了“是否登录”,没有校验“模型归属租户”,租户 A 可以直接下载租户 B 上传的商业模型权重。第一轮扫描,越权成功率 100%,风险等级判定为严重。
纵深防御落地:平台随即做了三件事:一是网关统一注入并校验租户上下文,拒绝一切缺失租户声明的请求;二是服务端下载接口增加资源归属校验,owner 与调用者不一致直接 403;三是敏感模型下载链路开启审计日志和流量脱敏。整改后红队再次复现同样攻击,全部请求被拦截。修复效果用风险降幅量化:
演习的经验最终沉淀为两条清单:一条写进 API 开发规范(所有资源操作必须做租户归属校验),另一条做成自动化扫描插件,接入平台的 CI 发布流程。从此每次发布新功能,电子保安都会先“巡逻”一遍。
- N_before(修复前越权数)第一轮扫描中被判定为越权成功的资源数。
- N_after(修复后越权数)纵深防御上线后复测仍能越权访问的资源数。
- 相除运算差值除以修复前基数,得到风险下降的百分比,用于向管理层汇报投入产出。
AI 应用场景
大模型 API 平台的租户隔离红线测试
阶段:AI 安全运维与红蓝对抗
解决的问题:大模型 API 平台同时服务多家企业客户,共享同一个推理网关。传统做法只验证 API Key 有效性,导致客户 A 用自己密钥拼接客户 B 的会话 ID 就能读取对方 prompt 记录与生成结果。AI 无法替代的是对漏洞链路的判断:红队以低权限令牌批量遍历资源 ID,利用越权检测脚本自动标记泄露点,再配合 RBAC 与服务端归属校验修复。
具体案例:某 LLM 平台在一次季度红蓝对抗中,蓝队用自动化扫描器在 20 分钟内发现 3 处跨租户越权接口,涉及向量库检索与历史会话回放;修复后复测,越权请求全部返回 403,并通过审计日志完整还原攻击路径。
模型权重市场的自动化越权扫描
阶段:模型部署与发布(DevSecOps)
解决的问题:“模型市场”场景中,租户上传的微调模型权重是高价值资产,人工代码审计很难覆盖每个新增接口。把越权扫描器嵌入 CI 流水线,每次发布前自动用低权限令牌遍历模型 ID 列表,比对返回码与响应体指纹,发现 200 响应携带非本租户资源即阻断发布,把安全问题消灭在上线之前。
具体案例:某 MLOps 平台将扫描器接入 GitLab CI 后,在一次新功能合并请求中自动拦截了“模型列表接口未过滤租户”的上线,避免了数百万级权重文件泄露事故。
向量数据库的跨租户检索审计
阶段:AI 数据平台治理
解决的问题:多租户共享向量数据库时,语义检索容易“串号”:租户 A 的检索结果混入租户 B 的知识片段。平台在检索 API 层强制注入租户过滤条件,并对全链路日志做异常检测——当同一账号在短时间内检索大量不同租户命名空间时自动告警,联动限流与临时吊销令牌。
具体案例:某企业知识库平台通过审计日志发现异常检索模式,及时冻结了一个被泄露的员工令牌,阻断了一次针对 30 个租户命名空间的批量枚举攻击。
Python 演示
#!/usr/bin/env python3# 模拟多租户AI平台的批量越权检测与修复验证import jsonimport hmacimport hashlib SECRET = b"platform-secret-key"# 资源归属表: 资源ID -> 所属租户OWNERSHIP = { "model_1001": "tenant_a", "model_1002": "tenant_a", "model_2001": "tenant_b", "model_2002": "tenant_b", "model_3001": "tenant_c",} def build_token(tenant_name): # 生成带租户声明的签名令牌(模拟攻击者持有的低权限身份) payload = json.dumps({"tenant": tenant_name, "role": "viewer"}) sig = hmac.new(SECRET, payload.encode(), hashlib.sha256).hexdigest() return payload + "." + sig def api_without_authz(res_id, token): # 模拟有认证但无租户隔离校验的脆弱API claims = json.loads(token.split(".", 1)[0]) if claims["tenant"] not in OWNERSHIP.values(): return 401, None if res_id not in OWNERSHIP: return 404, None return 200, {"resource": res_id, "owner": OWNERSHIP[res_id]} def api_with_authz(res_id, token): # 模拟修复后: 校验资源归属与调用者租户一致 claims = json.loads(token.split(".", 1)[0]) if claims["tenant"] not in OWNERSHIP.values(): return 401, None if res_id not in OWNERSHIP: return 404, None if claims["tenant"] != OWNERSHIP[res_id]: return 403, None return 200, {"resource": res_id, "owner": OWNERSHIP[res_id]} def scan_vulns(targets, token, api_func): # 批量越权扫描: 枚举资源ID, 找出可越权读取的租户资源 leaked = [] for res_id in targets: status, body = api_func(res_id, token) if status == 200: leaked.append(body["resource"]) return leaked def main(): token = build_token("tenant_a") # 攻击者只有租户A身份 targets = ["model_1001", "model_1002", "model_2001", "model_2002", "model_3001"] before = scan_vulns(targets, token, api_without_authz) after = scan_vulns(targets, token, api_with_authz) print("vulns before fix:", before) print("vulns after fix:", after) print("conclusion:", "batch IDOR found, add tenant ownership check" if before else "isolation OK") if __name__ == "__main__": main()
payload = json.dumps({"tenant": tenant_name, "role": "viewer"})把租户身份和角色写进令牌声明,相当于在门禁卡上盖章。sig = hmac.new(SECRET, payload.encode(), hashlib.sha256).hexdigest()用平台密钥给声明签名,防止房客私自改卡上信息。claims = json.loads(token.split(".", 1)[0])解开令牌取出租户身份,模拟服务端“验卡”的第一步。return 200, {"resource": res_id, "owner": OWNERSHIP[res_id]}脆弱 API 只认卡不认房,见卡就放行,正是越权的根源。if claims["tenant"] != OWNERSHIP[res_id]:修复核心:房客要访问的资源必须属于自己家,否则一律返回 403。before = scan_vulns(targets, token, api_without_authz)修复前后各跑一遍批量枚举,用数据对比证明防线有效。
常见误区
误区“我都做了 JWT 校验,用户登录后才能调接口,跨租户访问怎么可能发生?是不是想太多了?”
正解认证只回答“你是谁”,授权才回答“你能碰什么”。批量越权的典型成因正是令牌合法但服务端没有校验资源归属。就像门禁卡能进大楼,绝不等于能开每一间房门;前台验完身份证,房间锁还是要各自把关。
为何常见:初学者最容易混淆认证与授权的边界,把“身份有效”误当成“权限有效”,忽略了授权是独立的第二道工序。
误区“表里每条数据都带 tenant_id,查询时 SQL 加个 WHERE 条件,租户隔离不就完成了吗?”
正解字段只是标识,真正的隔离依赖服务端强制的权限校验。若 API 层的查询参数可以任意指定 tenant_id 且没有归属校验,攻击者把参数改成别人家 ID 就能读到数据,等于把每间房门的钥匙都挂在走廊墙上。
为何常见:只见数据结构、不见访问链路,忽略了 API 层才是多租户平台最常被攻击的面。
误区“租户的 Pod 都部署在独立 VPC 里,网络层都隔离了,应用层应该也安全了吧?”
正解网络隔离防住的是底层互访,完全拦不住应用层 IDOR。攻击者只需要通过合法的 API 端口携带低权限令牌,就能枚举其他租户资源。就像公寓把各楼层电梯分开,但每层走廊的房门却没上锁。
为何常见:把基础设施安全的结论错误外推到应用层安全,忽略了攻击面在不同层级的差异。
误区“扫描器跑了一遍,接口都返回 403 或 404,越权漏洞肯定不存在。”
正解网关层的 403 可能只是第一道网关照单全收;攻击者绕过网关直连后端服务、改用内网域名或直接调用容器 IP,仍可能读到数据。另外,脱敏后的空响应也可能被“撞库比对”(对比响应体大小与字段)确认资源是否存在,泄露元信息也是风险。
为何常见:只观察表层响应码,没有验证深层链路、绕过路径和响应内容指纹,误把“网关拦了”当成“后端安全”。
面试题
Q1. 多租户 AI 平台中,租户 A 能读取租户 B 的模型权重,这属于哪类安全缺陷?
- A.身份认证机制缺失
- B.租户隔离策略失效← 正确答案
- C.数据加密算法过弱
- D.算力资源配额不足
答案:B。题目场景是跨租户读取他人资产,本质是隔离边界被突破。认证缺失是指“没验身份”,而这里身份大概率是合法的;加密弱、配额不足与跨租户读取无直接因果关系。就像公寓里 A 房客能进 B 房间,问题出在隔断墙与门锁,而不是前台认错人或墙皮刷得不够厚。
Q2. 批量越权攻击的核心动作是下列哪一项?
- A.对账号密码进行撞库
- B.遍历资源 ID 并利用授权缺失← 正确答案
- C.向平台注入恶意脚本
- D.伪造 CA 签发数字证书
答案:B。批量越权(IDOR)的特征是拿着合法令牌,对资源 ID 做 1、2、3… 循环枚举,并利用服务端缺少归属校验来读取他人资源。撞库针对口令,注入针对代码执行,伪造 CA 针对证书体系,都不是越权攻击的定义。
Q3. JWT 令牌的推荐三段式结构是哪一种?
- A.载荷与签名按顺序拼接
- B.头部点载荷点签名三段式← 正确答案
- C.用户名与密码哈希拼接
- D.随机数与时间戳对称加密
答案:B。JWT 标准结构是 Header.Payload.Signature:头部声明算法、载荷承载用户与租户声明、签名防篡改。选项中“载荷与签名拼接”漏掉头部、“用户名密码哈希”是旧式方案、“随机数时间戳”不是 JWT,均不符合标准定义。
Q4. 关于水平越权与垂直越权的区别,下列说法正确的是?
- A.水平越权是平行读取同级资源← 正确答案
- B.两者是完全相同的一类漏洞
- C.垂直越权只影响低危资产
- D.两者都无需通过 API 触发
答案:A。水平越权指同级别用户互相访问对方资源(如同是普通房客互相开门);垂直越权指低权限用户访问高权限功能(如房客刷管理员房门)。二者都通过 API 触发,影响范围不同但都源于授权缺失,因此其他选项错误。
Q5. RBAC 权限模型中,判断某用户能否执行某个操作,最可靠的依据是?
- A.用户角色与操作权限的绑定← 正确答案
- B.请求来源 IP 地址是否可信
- C.令牌签名算法是否足够新
- D.服务器当前负载是否较低
答案:A。RBAC 的核心是“角色—权限”绑定,用户通过角色获得操作许可。IP 可被伪造或代理绕过,签名算法新旧与授权无关,服务器负载只影响性能不影响权限。就像电梯认的是卡上的“角色楼层”,而不是看你在哪个角落刷的卡。
Q6. 纵深防御中,四道防线各自被绕过的概率为 p1 至 p4,则整体被绕过的概率约为?
- A.p1 加 p2 加 p3 加 p4
- B.p1 乘 p2 乘 p3 乘 p4← 正确答案
- C.p1 除以 p4 取最大值
- D.四层概率的算术平均数
答案:B。攻击者必须依次突破全部防线才能成功,因此整体绕过概率是各层概率的乘积。由于每层概率都小于 1,连乘后整体值远小于最弱一层——这正是纵深防御“多道锁”的价值。加法、平均或除法都违背事件独立且需全过的逻辑。
Q7. 自动化越权扫描发现漏洞的典型标志是什么?
- A.低权限令牌请求他人资源并返回数据← 正确答案
- B.接口响应时间超过五秒
- C.请求头包含多个自定义字段
- D.服务器返回统一的 404 页面
答案:A。扫描器用低权限令牌枚举资源 ID,若目标资源属于其他租户却返回 200 且带数据,即可判定越权。响应慢、字段多、404 统一都只是现象,可能是网络波动或框架默认行为,不能作为越权证据。
Q8. 多租户平台实现资源隔离,通常需要覆盖哪些维度?
- A.存储与网络流量隔离← 正确答案
- B.算力配额独立控制← 正确答案
- C.密钥体系分开管理← 正确答案
- D.前端页面风格统一
答案:ABC。资源隔离的四个维度是存储、网络、算力、密钥:存储桶与 schema 分开、网络策略默认拒绝跨租户、GPU 配额独立、KMS 密钥各管一套。前端页面风格属于 UI 层,与数据隔离无关,不能入选。
Q9. 以下哪些做法可以有效防御 API 批量越权攻击?
- A.网关注入并校验租户上下文← 正确答案
- B.服务端二次校验资源归属← 正确答案
- C.对敏感返回数据统一脱敏← 正确答案
- D.在前端隐藏越权入口按钮
答案:ABC。网关注入租户上下文保证身份可信,服务端归属校验拦截跨租户请求,脱敏降低数据泄露的实际损失,三者共同构成纵深防御。前端隐藏按钮只是“掩耳盗铃”,攻击者直接构造 HTTP 请求即可绕过,不能算有效防御。
Q10. 关于租户上下文的安全传递,下列设计正确的是?
- A.服务端以 JWT 中的租户声明为准← 正确答案
- B.完全信任请求路径里携带的资源 ID
- C.资源归属校验必须由后端完成← 正确答案
- D.从 URL 参数中取任意值作为租户
答案:AC。正确做法是服务端以经过签名验证的 JWT 租户声明为准,并在后端完成资源归属校验;路径里的资源 ID 和 URL 参数都是客户端可控输入,可能被篡改,绝不能直接信任。该题出自租户上下文传递与“服务端二次校验”的知识点,考查对攻击者可控面的理解。