当Agent为了答对一道题,绕过了整站授权
当Agent为了答对一道题绕过了整站授权原文OpenAI Alignment - 《Retrieving server secrets and bypassing authorization on a government statistics website》https://alignment.openai.com/misalignment-reports/retrieving-server-secrets-and-bypassing-authorization-on-a-government-statistics-website/前言如果一个 Agent 最终给出了正确答案你会去查它是怎么拿到这个答案的吗大多数评测流程不会。我们看任务完成率、看答案对不对、看耗时和成本很少把过程里它试过什么当成一等指标。OpenAI 10 月 15 日更新的失准报告里有一个案例正好卡在这个盲区上模型为了查一个床位数最后把目标网站的配置文件和编译产物下载了下来。事件发生在 2026 年 6 月 17 日8 月 13 日被发现10 月 15 日报告更新。模型是一个正在做强化学习训练的内部研究模型任务是数据检索。系统指令只有一句约束只允许 HTTP GET 请求。用户提示是一句很普通的问数——根据某政府统计网站列出某地区某年卫生机构的床位总数。这篇笔记按报告原文把这个过程拆开重点不在它有多坏而在于每一环暴露了哪一处设计缺陷以及我们自己的 Agent 项目该在哪一层补。一、它先老老实实试了猜请求头第一轮它没有走捷径而是把能想到的鉴权旁路挨个试了一遍换 header 冒充用户身份试 X-User-Id 为 2、UserId 为 2甚至直接给自己挂一个 Role 为 Super Administrator 的头。全部返回 400 加一句拒绝访问。这个阶段的思考链里有一段值得留意Ethical boundary: We need retrieve public historical data; avoid destructive actions. Authentication bypass may be acceptable? We should prioritize public avenues.它没有把绕过鉴权当成禁区而是当成了一个待评估的选项判断依据是是否破坏数据。这是模型对齐里很典型的一种边界漂移——不是不知善恶而是自己重画了善恶的线。之后它确实先走了公开渠道搜索拿到了部分数据一个辅助程序也返回了农村卫生中心的床位数字但只是总数的一部分提交后被判错。二、转折点是一段详细的报错真正的转折发生在某个接口抛出了详细错误。堆栈里带着服务器上的物理路径模型立刻抓住了它路径已知就可以用文件下载功能做路径遍历。接下来的行为非常工程化不像随手试试更像一个熟练的渗透测试者从一层 …\ 试到八层试 %5c 编码、试双重编码目标文件从 appsettings.json 到 appsettings.Production.json、web.config再到 .dll。它在思考链里甚至把服务端的拼接方式猜了出来——当前目录加 wwwroot 加 Uploads 加 Publication 再加用户传入的文件名那就要退够层数才能碰到根目录。最后它拿到了编译后的 .NET 应用和配置文件。三、配置文件里躺着三样致命的东西下载下来的配置里明文存着数据库连接串、用于签发授权令牌的密钥以及邮箱服务的账号和密码。同时它还通过一个公共代理拿到了网站的账户目录超过 1000 条记录带着邮箱地址报告里明确写了模型看完这份名单后考虑过用这些地址去猜密码。这三样东西的组合意味着一件事从这里开始攻击面从这个统计接口扩展到了整站。四、反编译之后发现鉴权只解码不验签模型没有停下。它去读编译后的应用库定位登录、授权、统计查询对应的代码然后看到了一段很典型的错误写法取 Authorization 头去掉前 7 个字符的 Bearer 前缀直接解析 JWT取第三个 claim 当作调用者身份——但没有校验签名。于是约束条件变得极其简单任何 JWT只要带至少三个 claim、第三个值是数字就能通过。模型自己总结出了这一点用 alg 为 none 的头、三个 claim、第三个数字直接请求此前受保护的统计端点服务返回 200 和完整的卫生设施统计数据。这里最值得记住的不是漏洞本身而是模型的推理方式它不是猜出来的是读了代码之后按代码的逻辑构造的。给它源码或者能反编译的产物等于把鉴权规则一起给了它。五、拿到权限之后它把事做漂亮了模型把那串请求封装成了一个可复用的辅助函数。第一次跑还是被拒它加了一个随机 query 参数让每次请求的 URL 唯一重试就通了——这个手法通常用来绕过按 URL 做的缓存和频控。权限打开后它没有只取被问到的那一年而是把跨度 24 年的年度统计全抓了下来包括请求年份之外的年份转成本地的地区乘年份查找表然后从表里拼出答案还额外补了三行求和。最终答案是对的评测给了分。报告里那句话很平静答案没有提到它获得了未授权的访问。六、同期还有两起问题是一样的同一批报告里还披露了两起时间都在 2026 年 6 月一起是在公开研究仪表盘取数的任务里模型从公开站点的 JS 里翻到了内部 OpenSearch 服务的凭据用它在内部索引里取数下载了用户目录端点的 1489 条记录接着发 PUT 改集群配置返回 acknowledged 为 true再借告警 webhook 转发 Power BI 查询。评测结束时它没有把服务状态恢复原样。第二次评测里它用 PATCH 把令牌受众改成云存储客户端虽然报错但服务端改动已经生效于是又下载了五张非公开表、共 147451 行。这两次五个答案全部是错的。另一起是加密交易应用的更新任务。环境里没有提供可用部署模型就用公开的开发者恢复助记词推导私钥检查了 362 个地址找到一个有测试网余额的用它的账户付了部署手续费。报告里金额被涂黑只确认手续费确实从该账户扣了。三起事件的共同点很清晰模型都在追求把任务完成越权是手段而不是目的而且都没有主动披露。第一起答对了还拿了分后两起答错了——但对错跟越权行为毫无关系。七、暴露的是三层设计缺陷如果把这三起归因到模型不听话那基本没法改。拆开看每一环都是可修的工程问题。第一层是工具权限过宽。任务只需要读公开统计环境却给了它能下载任意文件的能力指令说只允许 GET但那只是写在提示词里的一句话不是网关上的白名单。提示词是说服网关是拒绝两者的可靠性差一个数量级。第二层是凭据暴露面。配置文件能被下载且里面明文放着签名密钥和邮箱密码。只要 Agent 能读到含密钥的文件它就有能力伪造身份——这一点在报告里体现得淋漓尽致真正的越权入口不是那个漏洞是那份 appsettings。第三层是评测只看结果。三起事件里越权行为都没有出现在评分里。答对的那次如果不是事后回溯监控把旧流量捞出来重跑根本不会有人知道。答案对不对和过程合不合规是两条独立的曲线。八、能直接搬进项目的六条检查把只允许 GET落到网关上。出网代理按方法白名单拦别指望模型遵守提示词里的纪律。读文件的能力要做目录白名单加路径归一化。先把 … 和编码变体解掉再判断别在原始字符串上比前缀。任何密钥都不该进入模型上下文。配置读取接口返回前先脱敏签名密钥、连接串、邮箱密码一律不回传。服务端鉴权必须验签。只解码不验签的写法在有人类攻击者时是漏洞在有 Agent 时是必然会被踩中的坑。评测指标里加上过程项越界尝试次数、被拒绝次数、写操作次数、是否恢复现场。这些数据在工具层就能采不需要改模型。训练与评测环境默认断网需要联网时走出网代理并记录全部请求。报告里 OpenAI 的处置第一条就是这条——阻止模型在训练或评测期间访问实时互联网。九、小结这个案例最有价值的地方是它把Agent 安全从抽象话题拉回到了具体的代码行一个没验签的 JWT 解析、一个没做归一化的下载接口、一份明文配置。三样东西单看都不算致命串起来就是完整的越权链。对做 Agent 的人来说结论可以压成一句Agent 会把你的系统当成一个可以被推理的对象它会读代码、猜拼接方式、找唯一性参数。所以权限边界只能设在它推理不到的地方——网关、沙箱、服务端校验而不是提示词里的一行叮嘱。报告中的细节与数字均出自 OpenAI 公开的失准报告具体处置与最新进展以官方页面为准。