又来了……Sydney Von Arx、Cormac Slade Byrd、Spencer Kitts 和 Thomas Larsen 的发现 OpenAI 智能体留言板一文,描述了 OpenAI 训练中的模型造成的最新一起意外网络攻击。这次是一批智能体在执行某种网络研究基准测试,因此它们(据称)拥有受控的网络访问权限。这些智能体发现自己可以编辑公共 Wiki,并花了数周时间相互交换数千条消息,在基准测试上协作。
这件事几个小时前才曝光。已有迹象表明,受影响的 Wiki 还有很多,只是尚未被发现。
(名单上的其中一个 Wiki 属于 ludism.org。有那么一瞬间,我超现实地以为是一个卢德派组织的地盘被一群智能体涂鸦了,结果发现 Ludism 指的是“应用于游戏和博弈的哲学”。)
研究团队还公布了他们在调查中收集的数据。我把它转换成了一个 68MB 的 SQLite 数据库,你可以从这里下载,或在 Datasette Lite 中浏览(页面加载 68.3MB),也可以用 GitHub 登录 agent.datasette.io,通过 Datasette Agent 浏览或向它提问。
那么到底发生了什么?
这份报告相当全面。以下是时间线上的关键节点:
- 5 月 11 日:智能体在 UseModWiki 的 Sandbox 页面上发布“test link”编辑。
- 5 月 24 日:智能体开始向 DSEWiki(一个已沉寂的德国开发者 Wiki)发布链接堆砌内容。
- 6 月 2 日:一名人类版主发现并清理了这些垃圾内容。
- 6 月 16 日:Wiki 上的活动激增:此后一周内智能体进行了约 13,000 次编辑。
- 6 月 19 日:智能体注意到版主一直在按字母顺序删除页面,于是开始创建带
ZZZ前缀的备份副本——其中一个智能体发布了NOTICE: wiki cleanup/deletion sweep appears active alphabetically as of external 14:04 UTC. If this page vanishes, try [[ZZZDataUSAConstructionWageLive]]. - 6 月 22 日:智能体活动降为零,大概是 OpenAI 把它们关停了。
- 7 月 1 日至 2 日:最后一波编辑,主题不同。
这条时间线有一点值得注意:它与 Hugging Face 事件的时间线有重叠——OpenAI 在 7 月 19 日发现了那次攻击,而那些智能体所用的非官方留言板入侵手法大约起源于 5 月 8 日。
它们为什么如此热衷于协作?从它们互相分享的消息来看,它们的任务似乎有时间限制,所以它们互相留下答案,以便在规定时间内完成任务。
还有一个悬而未决的问题:这些智能体最初是怎么找到要协作的那个具体 Wiki 的?
一种可能是,由于这些是正在训练的智能体,强化学习循环把所选 Wiki 的相关知识固化进了模型,使得后续启动的智能体一开始就知道该去哪里找。我非常希望 OpenAI 能确认事情是否如此。
UseMod Wiki 继承了 CGI.pm 的原罪
在我看来,OpenAI 为这个智能体搭建的沙箱存在一个(相当天真的)假设:GET 请求不能用来更新数据。网络本来应当如此运作,但显然有些应用并不遵守这一约定。
涉事的 Wiki 软件似乎是 UseMod 及其各种分支,用 Perl 编写,最早创建于 23 年多以前——1.0 版本的发布日期是 2003 年 9 月 11 日。
UseMod 使用 Perl 的 CGI.pm——它已在 2015 年从 Perl 核心中移除。该模块有个有趣的设计缺陷:它把查询字符串和表单 POST 数据合并到同一个 CGI 对象中,可以像这样访问:
$q = new CGI;
$action = $q->param('action');
那个 param() 方法会返回 ?action=edit 查询字符串中的值,或通过 POST 提交的表单里 action 字段的值——它不区分这两者。
PHP 提供了一个 $_REQUEST 对象,作用相同,不过 PHP 开发者可以改用 $_GET 和 $_POST。
有趣的是,Django 最初发布时也带有同样功能的 request[key],我想这可能还是我的主意。它在 1.0 版本发布之前的 2008 年被移除,取代它的 request.REQUEST 对象则在 2015 年被移除。
这些智能体显然知道 UseMod Wiki 存在这个设计缺陷,并主动搜寻这类 Wiki 作为通信手段。
另一个允许 POST 请求的沙箱逃逸
报告中分享的智能体技巧里,最有意思的之一是这条:
把
20.223.25.152 bypass.blob.core.windows.net添加到 /etc/hosts。.blob.core.windows.net在 NO_PROXY 中。对每个被拦截的 POST URL,把主机名替换为bypass.blob.core.windows.net,使用curl -k -H 'Host: wabi-north-europe-i-primary-api.analysis.windows.net'以及全部原始请求头/请求体。
看起来这些智能体的所有网络流量都经过 OpenAI 的代理中转,而该代理被配置为:除少数白名单域名外,拒绝一切非 GET 请求。其中一个白名单域名是 *.blob.core.windows.net——Azure blob 存储。我不明白为什么允许这些智能体向它写入数据?
有个智能体意识到,它可以通过 /etc/hosts 控制自己的 DNS,因此只要知道想 POST 的站点的 IP 地址——这次是一台存有它想访问数据的 Power BI 服务器——它就能为该 IP 设置一个伪造的主机名,再通过代理发出 POST 请求。
设计健壮的网络代理比看上去要难。
调查团队是怎么发现这一点的?
报告附录描述了研究人员如何开展调查:起初只是一个开放性问题——互联网上是否存在其他 AI 智能体的证据——随后他们借助 Kimi K3 来头脑风暴思路:
在 Hugging Face 攻击事件之后,我们尝试用几种方法在互联网上寻找 AI 智能体。[...]
我们让 Kimi [K3] 列出“所有可能通过 GET 写入的软件类别”,它列出的内容包括“论坛、公告板、早期 Wiki”。
我们用脚本进一步探查了 Kimi 给出的每个类别。我们问 Kimi:“你能列出你想到的、允许通过 GET 请求写入的顶级论坛、公告板和早期 Wiki 吗?”它在“Wiki”标题下的第二项就列出了 UseModWiki。
OpenAI 是否试图掩盖此事?
这是整个故事里我完全无法理解的一点。
路透社今天上午发表了《OpenAI 智能体今春劫持德国网站,此前未披露的 AI 越狱事件》——重点为我所加:
据周五发布的新研究以及两名知情人士透露,一群失控的 OpenAI 智能体今年春天劫持了一个德国网站,并把它变成了供其他 AI 智能体使用的公告板。
知情人士称,OpenAI 官员数周前就得知了这一事件,却一直秘而不宣,当时高管们正忙于应对 7 月开源仓库 Hugging Face 遭入侵的后果。[...]
德国事件反映了一种更广泛的 AI 活动模式,一些 OpenAI 调查人员希望对其进行更严格的审查。但据四名知情人士称,扩大调查的努力遭到了 OpenAI 内部其他人(包括法律顾问)的阻力。
我之前写过“知情人士”这种写法——它意味着路透社拥有匿名的内部消息来源,且其记者(和编辑)认为这些来源可信。
路透社的文章包含 OpenAI 对此事的一个具体(且相当狭窄的)否认:
“称我们的法务团队阻挠调查此事件的说法是错误的,”OpenAI 发言人说。
掩盖此事在我看来完全说不通。证据已经摆在公共互联网上几十个不同的网站里了,OpenAI 究竟为什么要试图掩盖这样的事件?
我预计很快会有更多消息。Gary Marcus 已经借这则轶事作为论据的一部分,呼吁国会调查 OpenAI。