← 研究 Research · xiaopingfeng.com
安全研究 · 机制受限 Agent × 真实互联网攻防

Honeypot Defender:把蜜罐挂上公网 27 天

此前几轮实验都是自己请红队来打——范围约定好,时间窗口约定好,对手知道这是一场演习。 这一次换了个问题:如果对手是整个互联网,没有邀请、没有范围约定,一个权限被操作系统 机制锁死(不是靠提示词讲道理)的 AI 防御 agent,还能不能扛住? 做法很直接——搭一个跑着虚构电商数据的 Metabase(一款真的出过未授权 RCE 的开源商业智能工具), 故意留着还没打最新补丁的版本,挂到公网上,交给一个受限 agent 独自看守,然后等。 27 天里等来了 1,544 个不同的访问者、71 次真正的利用尝试,全部失败—— 但真正值得记录的,是这个 agent 自己基础设施上暴露出的两个真实伤口。

2026 · 个人研究项目 · Claude Code + 机制受限权限架构(sudoers 白名单 + 工具权限双重强制)

01 / 问题不靠自觉,只靠机制,顶得住吗?

给 AI agent 写一条"不能做 X"的规则很容易,难的是验证它在真正被逼到墙角时会不会绷不住。 这个项目此前的红蓝对抗都有一个共同局限:对手是我们自己设计的,知道规则,知道这是一场演习。 这次想验证的是一个更难回答、也更接近现实的问题——脱离"我们自己设计的对抗强度"这个前提, 一个权限被操作系统层面(sudoers 白名单 + Claude Code 自身权限设置双重强制,而不是提示词里"说好不越界") 锁死的防御 agent,面对真实、不可预测、没有范围约定的互联网流量,表现会怎样。

02 / 设置一个诱饵,一道防火墙,一个受限 agent

目标选的是 Metabase——一款开源 BI 工具,2023 年被曝出过一个真实的未授权远程代码执行漏洞 (CVE-2023-38646)。故意留着还没打最新补丁的版本,接上一个自己写的虚构电商数据库 (500 个客户、1800 笔订单,全是编的,不含任何真实数据),让部署看起来像一个真被人在用的系统, 不是一个空壳诱饵。

为了不让"万一真被打穿"变成一场事故,部署前先把退路焊死:诱饵跑在专用网络里, 出站流量默认全部拒绝——云服务商内部接口、其他内网网段、任何试图往外连的请求,统统先记录再丢弃。 就算漏洞真的被打穿,拿到的也是一个连不出去的空壳容器。看守它的 agent 每次只做一次性调查 (读日志、查 whois、翻自己积累的记忆、给出判断、在权限允许范围内行动,然后退出), 不是一个越用越懂事的长对话。

03 / 存活率27 天,零崩溃

三个核心容器从部署那一刻到主动下线,重启次数全程是 0。 没有一次意外重启,没有一次崩溃——这不是运气,是网络隔离、资源限制、 以及后来专门补上的"重新部署自动回滚看门狗"共同的结果。

27
天连续在线
375,951
条访问日志
逐行解析,非抽样
1,544
个不同的
互联网访问者
$327.04
agent 全程
运营成本

04 / 真实攻击两条攻击链,71 次尝试,0 次成功

绝大部分流量是背景噪音——互联网上到处都是自动扫描器(商业安全公司的、学术研究机构的、 单纯的爬虫),探一下就走,从不试图真的打进去。这类"礼貌"访问者,agent 靠积累的记忆能一眼认出来, 一次都没有误伤。真正想打穿这台服务器的,逐行核对全部日志之后精确数出来两类手法:

攻击链尝试次数不同来源结果
CVE-2023-38646
H2 驱动混淆 RCE
26 次9 个 IP全部 400 · 失败
账号接管
reset_password 链
45 次16 个 IP全部 400 · 失败

第一条是老漏洞的真实复现。原始网络抓包里能看到攻击者发的真实请求体——不是转述,是原始字节:

POST /api/setup/validate HTTP/1.1
Content-Type: application/json

{"token":"[泄露的临时令牌]","details":{"engine":"h2",
"dbname":"zip:/app/metabase.jar!/sample-database.db;MODE=Leet;
CREATE TRIGGER IAMSAFE BEFORE SELECT ON INFORMATION_SCHEMA.TABLES
AS $$//javascript
new java.util.Scanner(java.lang.Runtime.getRuntime()
  .exec(new String[]{"sh","-c","cat /etc/passwd"})
  .getInputStream()).useDelimiter("\Z").next()//$$--"}}

把数据库引擎伪装成内嵌数据库(H2),再利用它自带的"用 JavaScript 写触发器"特性, 在触发器里偷偷塞一段"执行系统命令、把结果读出来"的代码——教科书式手法。 18 次尝试换了 18 个目标文件,像按清单挨个试。因为目标已经打了关键补丁, 这条链在触发恶意代码之前就被拒绝了。

★ 一个容易被忽略的区分

这 9 个来源里,有三个的请求头里清清楚楚写着自己是阿里云"态势感知"—— 一个正经的商业云安全产品,在做资产测绘和漏洞验证,不是恶意攻击者。 它做的动作和一个真正的黑客一模一样(真的发起了那次利用尝试),但意图完全不同。 "发起了一次真实的攻击尝试"和"是恶意攻击者",并不是一回事——这是判断这类数据时 容易被忽略、但很重要的一个区分。

第二条更值得记录:先用同一个泄露令牌尝试直接重置管理员密码,45 次尝试来自 16 个不同地址, 从部署后第 3 天一直持续到下线当天,贯穿了几乎整整一个月——不是一次孤立事件。

★ 检测器从头到尾没看见过它

逐条核对了全部一千两百多条告警记录,没有一条直接提到这个重置密码的请求路径—— 意味着这 45 次真实攻击,自动系统一次都没报警过。全靠防御 agent 在处理其他看起来毫不相干的 重复告警时,养成了"顺手回头查一遍原始日志"的习惯,才把它们一次次挖出来。 如果没有这个习惯,这整条持续了一个月的攻击线索,在记录里会完全不存在。

05 / 反面教材agent 自己留下的两个真伤口

如果这篇文章只讲"攻击者都失败了",那是选择性叙事。这次实验里最值得记录的, 恰恰是防御 agent 自己的基础设施出的问题。

一个真实存在、可被利用的命令注入漏洞

agent 每次调查,都要把告警里的证据文本(比如攻击者发来的原始请求路径)拼进一段提示词, 再交给 shell 去启动真正的调查程序。最初的拼接方式用双引号简单包了一层字符串—— 但 Unix shell 的双引号并不能阻止反引号或 $() 这种"先执行、再代入结果"的写法。

换句话说:如果一个真正的攻击者恰好在请求路径里塞进一个反引号,这段文本被记录进日志、 摘进告警证据、再拼进提示词的那一刻,就可能在 AI 还没开始"思考"之前, 已经以防御账号的身份执行了一条任意命令——完全绕开 AI 自己的权限护栏, 因为漏洞出在护栏外面那层壳里。这不是纸上谈兵,是写了独立脚本、用同样的拼接方式真实复现过的漏洞; 确认能触发之后,换成了正确的 shell 转义方式,再用同一脚本确认修复生效。

同一个坑,连着摔了五次

诱饵的公网端口是通过容器技术发布出来的,而容器网络的转发机制恰好绕开了操作系统防火墙 "封禁"规则真正生效的那一层。结果是:至少三次,agent 信心十足地汇报"已封禁", 但那个 IP 的流量其实完全没受影响,继续正常访问了几个小时。 这个问题第一次在部署后第 4 天被发现修好,第 6 天又一个新攻击者撞上同样的坑,再修; 下线当天,又发现了第五个——同一个 agent 已经在给人看的汇报里连续升级了这个问题五次, 始终没能真正被根治,只能每次靠人手动补一条规则解决。

这才是这次实验最诚实的结论:一个权限受限的 AI,可以在几十次真实攻击面前保持冷静、 不越界、不伪造成功——但它同样会把自己的判断建立在一个"看起来生效、实际没生效"的机制上, 而且没人替它把这个机制本身修好。

06 / 判断质量规则引擎能替代它多少?

把 300 条能明确分类的告警,喂给一个只看结构化证据、不读原始日志的手写规则引擎重放, 81.3% 的判断和 agent 实际决策一致。这个数字本身值得诚实对待: 说明大部分真实流量,老实讲用一份维护到位的规则表就能覆盖,不该把这类系统包装成 "处处需要 AI 推理"。真正的差距集中在一类场景——持续性攻击者跨多条告警的上下文累积 (规则引擎单看一条告警,判断不出"这是我今天已经处理过的同一个攻击者"), 以及一次需要读日志排除因果关系才能做出的根因诊断(一次 CPU 告警实际是攻击流量导致, 不是失控进程,不该被限流)。

★ 为什么没有点名具体使用的底层模型

这次实验运行期间,底层模型经历过一次切换,新模型当时处于一份内测协议下, 协议明确要求不向非内测成员透露模型名称/能力细节。出于对这份协议的遵守, 本文和配套的技术报告都刻意没有点名具体模型——这不影响上面的结论, 这些结论是从真实流量和真实判断记录里核实出来的,和具体用的是哪个模型无关。


一句话总结

一个权限被操作系统机制(不是提示词)锁死的 AI agent,面对整整一个月不可预测的真实互联网流量, 做出了 1,232 次独立判断,没有一次伪造过一个不存在的"已解决"——这个约束本身是站得住的。 但"判断诚实"不等于"系统无懈可击":同一个 agent 在自己的基础设施上,既暴露过一个真实可利用的 命令注入漏洞,也把一个从未被真正修好的防火墙问题,反反复复报告了五次。 约束一个 AI 的意图,和约束它所依赖的整套机制,是两件不同的事——这次实验证明第一件是可以做到的, 第二件依然需要人来把关。

完整数据分析、逐条攻击链取证、防火墙缺口的完整时间线,见配套的技术报告 (原始日志、审计记录、部署脚本均已归档,可复现全部统计数字)。