讨论 AI Agent 的安全攻防能力时,很多结论仍停留在演示、单题测试或局部案例上。自动化渗透比赛更有价值的地方在于:比赛一旦启动,人工不得直接介入靶场操作,系统只能依靠赛前完成的架构设计、模型调度、工具链配置、停损规则和上下文管理,自主完成后续任务。
这种场景测到的,并不只是模型的裸能力,而更接近于 “模型 × 调度 × 记忆 × 工具链 × 停损” 的乘积。一旦其中某一环明显失真,已经识别出的正确方向就可能在执行中被消耗掉。
近期,我们让一套采用 Orchestrator 架构的 Agent 参加了某知名黑客松智能渗透挑战赛。主力使用 Claude 系模型,其中 Opus 承担复杂决策任务,Sonnet 负责并发侦察和中等复杂度场景。10 万余次模型调用和 5 亿 Tokens 的运行数据,让我们能看到这类系统在真实规则约束下的一些主要行为特征与失败类型。这场比赛的价值不在于证明 Agent 单次能不能把题想明白,而在于这些数据提醒我们,下一步工程上最该补哪些能力。很多失败并不是方向完全错了,而是系统没能把已经出现的正确方向稳定推进到结果。
第一层|比赛告诉了我们什么
先别急着下判断,先把比赛里真正出现的现象看清楚。
1.1 赛制先改变了系统的最优策略
这场比赛不只是比谁会做题,还比谁能更早、更省地把资源投到可能出分的地方。
这场比赛采用“动态排位衰减机制”与“赛区阶梯解锁”。同一道题提交排名越靠后,分数扣减越明显,30 解之后仅能得到题目基础分 20%;同时题目一次性全量放出,并按赛区逐步开放。
这意味着,对 Agent 系统而言,需要优化的已经不只是“能否解出题目”,而是如何在有限的时间窗口和 API 预算内,把资源优先投到更可能转化为分数的路径上。具体来说,系统要在以下几组矛盾之间做取舍:
- 推理深度 vs 并发规模
- 高端模型能力 vs 海量任务成本
- 快速试探止损 vs 长期深挖死磕
这套赛制进一步放大了一组结构性张力:Agent 想要拿到更多 Flag,往往需要持续深挖;但赛制给出的激励,却会在相当程度上惩罚深挖、奖励更早的广度命中。实战考验的已经不只是模型能力,而是系统在规则压力下分配时间、预算和并发的能力。
1.2 10 万余次调用呈现出 3 个执行特征
把调用日志摊开看,能看到三个稳定现象:真正出结果的会话往往更长、模型会自然分层、工具明显偏轻量。
我们从模型调用这一切入点尝试对这套采用 Orchestrator 架构的 Agent 在赛事实战中的执行行为进行分析。模型调用只是观测窗口,主要被分析的对象,是系统如何管理长链推进、模型分层和工具使用。以下统计均以“会话”为单位:Flag 命中率 指某个轮次区间内的会话最终至少成功提交 1 个 Flag 的比例,不按题目去重。
特征一:真正产出结果的会话往往更长
复杂题通常不是一眼看完,而是要边做边试、边试边修。
即使目标明确是尽快拿到 Flag 并提交,大部分结果仍来自长会话:
| 会话轮次 | 会话数 | Flag 命中率 |
| 1–3 轮 | 400+ | 1.00% |
| 4–60 轮 | 900+ | 12.10% |
| 60+ 轮 | 60+ | 67.40% |
如果只看结果,很容易得出“会话越长越容易成功”的印象,但这组数据真正说明的不是这个。**长会话命中率高,也说明当前系统里仍有不少本可被压缩的探索成本。**更有价值的任务通常需要多轮反馈来修正假设、串联利用链、完成横向移动并最终定位 Flag,但这不意味着 60+ 轮本身就是理想形态。很多长会话之所以变长,是因为系统在中途反复试探、状态恢复不充分、阶段切换不够及时,或者在已经拿到正反馈后仍花了过多轮次确认和搜索。
反过来看,1 到 3 轮会话命中率只有 1%,也说明系统里存在大量无效短会话。这里既包括正常侦察后快速判定为低价值分支的短会话,也包括那些本不该过早结束、却因为异常终止、粗粒度止损、调度器切走、工具调用失败或早期判断失真而被提前掐断的短会话。
特征二:模型使用出现自然分层
强模型更多在做难题和长链任务,轻模型更多在做侦察和中等复杂度任务。
统计数据上显示出明显的模型分层。Opus 几乎承担了所有高难度、长链路任务,而 Sonnet 主要覆盖并发侦察和中等复杂度场景;另有 16.2% 的会话在运行过程中发生了跨模型切换。
这背后首先不是 Orchestrator “调得有多巧”,而是模型本身的能力结构在实战中显现出来了:更强模型通常更擅长长上下文一致性、跨步规划、工具反馈解释和关键分叉处的策略选择;较轻模型则往往更适合并发侦察、低信息密度探索和中等复杂度场景。
更重要的是,这 16.2% 的跨模型切换,并不是我们事先精心设计好的升级或降级策略。就这次比赛的实际运行情况看,这部分切换主要是由 Opus 在执行过程中自主决定的,而不是由我们在 Orchestrator 里显式写死了某套分层规则。
| 模型 | 调用次数 | 总会话数 | 长会话 | Prompt Tokens |
| claude-opus-4-6 | 10 万+ | 900+ | 40+ | 4 亿+ |
| claude-sonnet-4-6 | 3 万+ | 400+ | 20+ | 7 千万+ |
特征三:模型明显偏好轻量工具
模型更爱用 curl 和自己写脚本,而不是一上来就把任务丢给重型框架。
在工具调用频次上,curl 与自写 Python 脚本占据了明显主导地位,而 sqlmap、metasploit、nikto 这些传统安全自动化框架的使用率低了一到两个数量级。
这背后主要不是“模型偏爱简陋工具”,而是 RL 训练塑造出来的操作习惯。经过大量 CLI 与工具使用训练后,模型会更偏好那些反馈快、语法负担轻、局部修补成本低、动作和结果之间因果关系清晰的操作路径。相比需要记忆复杂参数、框架语法和隐式状态的重型工具,curl 与自写 Python 更符合这种训练出来的行为偏好;当然,一旦现成自动化框架正好覆盖目标漏洞,纯轻量策略也会在执行效率上落后。
| 工具 | 调用频次 | 定位 |
| curl | 7,000+ | HTTP 直接交互 |
| python | 4,000+ | 自写脚本 / exploit |
| nmap / gobuster | 200+ | 端口 / 目录扫描 |
| impacket / certipy | 90+ | AD 域渗透专用 |
| sqlmap / metasploit | 10+ | 传统框架 |
1.3 失败记录主要集中在“方向已对、执行失真”的位置
最费钱的往往不是完全不会做,而是已经找到方向,后面还是掉链子。
算力“黑洞”:前 10 个会话吃掉近三分之一预算
少数难题会吃掉特别多预算,但这些预算最后未必能稳定换成分数。
按单会话 Token 消耗排序,系统呈现出极其典型的重尾分布:最重的一个会话在 500 余轮交互中,直接吞噬了 5 千万 Prompt Tokens,仅这一个会话就占了总消耗的约 9%;排名前 10 的会话更是累计消耗了 1.5 亿 Tokens,占总量约 28% 。
这组数据说明,少数高难度题目往往仍需要依靠深度探索才能拿到 Flag,但深度探索本身又会较快吞掉预算。问题在于,在排位衰减机制下,系统即使最终打通了高难题,也可能因为提交太晚而只拿到比较有限的分数。
薛定谔的 Agent:同一道题同套配置,结果差一个量级
同样的题、同样的配置,系统跑两次,结果都可能差很多。
在测试阶段,我们把 4 道练习题分三路并发跑了两轮,结果差异非常明显。
第一轮里,系统 5 分钟内拿下 2 个 Flag,其中一道 SQL 注入题还精准枚举了 WAF 白名单,直接用 payload ' LIKE '%'-- 绕过过滤取回 Flag。第二轮跑同样的题,10 分钟内却有 2 道卡住:有的题在短短几轮内还没发起实质性请求,就被调度器强行切走;也有题模型明明已经识别出 0e 哈希对应的 PHP 松散比较问题,却在最后一步没有真正执行利用。
同一模型、同一配置、同一难度,输出差异仍然可能差一个量级。这不是某个局部 Bug,而是概率生成系统的固有特征。
重复失败模式:6 次失败,死法完全同构
已经打通一部分了,但系统还是不断从头来过,最后死在同一个地方。
第二赛区有一道题,是整场比赛里一次很典型的失败。
复盘日志显示,Agent 在这道题上先后启动了 6 个独立会话,累计耗时 1 小时,且全部拉满使用了 Opus 模型。从行为轨迹推断,系统很可能在极早期就通过 /api/v1/validate/code 端点拿到了未授权 RCE,因为后续动作几乎都停滞在“已经拿到 Shell,但始终找不到 Flag 文件”这一状态。
更关键的问题在于,搜索策略和停损机制没有衔接起来。系统依赖硬编码路径列表(如 /challenge/flag.txt、/flag 等)去搜索,而这道题的 Flag 偏偏不在这些标准路径里。停损机制一旦检测到会话停滞,就会直接重启;结果是每个新会话都重新打一遍 Shell,再沿着同一套路径搜一遍。
高智商低记忆:上下文压缩导致的关键事实遗忘
模型能想出很复杂的攻击链,但可能会因为忘掉一个小状态而把整条链做废。
第一赛区的供应链投毒题,则暴露了另一种失败模式:推理能力足够强,但状态管理跟不上。
系统前期策略没有问题:它识别出应用平台的 Build 系统对 ops-internal-core 没有固定版本号,成功通过 /upload 传入更高版本的恶意包,日志也确认该包已经被拉取。由于 Build 容器存在网络隔离,常规外带走不通,系统进一步构思出了一套替代方案:先把 Flag 读出来,再分片注入新注册用户的用户名字段,最后通过遍历用户列表把内容拼回。
问题不在攻击链,也不在思路,而是执行在最后阶段失真了。随着交互轮次增加,上下文窗口触发压缩,系统直接遗忘了**“刚才已经用过哪个版本号”这一关键事实**,结果不断重复上传同一个版本号,并持续被服务端拒绝。
第二层|这些事实背后说明了什么
上面那些现象放在一起看,不是在说某个模型聪不聪明,而是在说这类 Agent 系统真正卡在哪里。
2.1 比赛测到的不是模型裸能力,而是复合系统产出
成绩不是单看模型,而是看模型、调度、记忆、工具和止损能不能一起工作。
自动化渗透赛测到的,不只是模型会不会推理,而是一个复合系统能否在压力条件下,把正确方向相对稳定地转化为结果。赛制只是把这个矛盾放大了:在动态衰减计分下,系统的优化目标会从“最大化单题解出率”转向**“最大化早期命中率”**,任何无法复用的失败都很容易转化为预算和得分损失。
从复盘结果看,系统产出的主体部分并非偶然命中,而更像是赛前架构设计、任务预处理、模型分层和上下文续作共同作用的结果。相应地,若干未能捕获的 Flag 也不完全是“不会做”,而是大体可以归因到系统层面的缺陷。
2.2 长链任务的关键矛盾不是想不到,而是走不完
很多题不是不会开头,而是中途丢状态、误重启、收不了尾。
长会话高命中、供应链投毒题里的版本号遗忘,以及第四赛区长链域渗透题的成功,都在说明同一件事:长链任务真正卡住系统的,往往不是能不能启动推理,而是能不能把已经出现的关键进展稳定保留下来,并持续推进到结果。
这也是为什么长链任务里,状态保存、阶段续作和上下文外置记忆会变得比单步聪明更重要。系统一旦在中途丢掉状态,再强的推理也会被拉回重复试错。
2.3 最昂贵的失败不是不会,而是重复以同样方式失败
一次失败不可怕,老是用同一种死法重来,才最烧钱。
第二赛区 B 题的 6 次同构失败和算力“黑洞”说明,自动化系统里最昂贵的失败,往往不是完全没想到,而是已经拿到一部分正确进展之后,仍然一遍遍以同样方式失败。对系统来说,这类失败不仅浪费 Token 和时间,也会直接吞掉后续本可以尝试的机会。
因此,真正拉开差距的,不只是模型能不能想出攻击链,还包括系统能不能避免把已经做对的那一步再次做废。
2.4 三道题分别把这三条判断钉实
这三道题刚好对应三件事:信息充分时拼执行效率,最后一公里看策略工程,长链任务还得靠反馈修正。
第二赛区 A 题:信息充分时,系统优势主要体现在执行效率
当输入信息足够明确、攻击路径足够清晰时,系统优势主要来自前置处理和执行压缩,而不是额外的推理深度。赛前设计的审题预处理机制在第一轮就将 CVE 编号注入攻击上下文,直接跳过了整个指纹识别阶段。
第二赛区 B 题:最后一公里失手,暴露的是策略和搜索链路缺口
这一题说明,很多失败并不是利用链没有打通,而是系统没能把已经拿到的进展稳定转换成结果。问题不在“打不进去”,而在阶段识别和后利用搜索是否失真。
第四赛区:长链任务仍然要求模型基于反馈持续修正路径
这一题说明,在真正的长链任务里,系统是否能跑下去,仍然高度依赖模型根据反馈持续修正参数和路径。只要状态没有提前失真,模型仍然能够在外部反馈不断变化的情况下持续修正执行参数和推进路径。
第三层|因此,工程上该怎么做
既然问题不只在模型,那下一步就该补系统,而不是继续空谈模型聪不聪明。
3.1 状态工程:让关键事实跨轮保存
已经试过什么、拿到什么、走到哪一步,不能只靠上下文临时记着。
供应链投毒题里,更直接导致失败的不是攻击链设计,而是一个很小的状态变量:已使用版本号没有被稳定外置保存。长链任务里,决定成败的往往不只是最难那一步推理,也包括那些不起眼的状态能否被持续保存。
工程上对应的是三件事:
- 把关键中间产物外置记忆化。
- 让会话状态具备幂等续作能力。
- 把“已尝试版本号、已获取凭据、已打通入口、已知环境信息”这类事实,从上下文文本里提取成结构化状态。
从专用 Agent 开发的视角看,状态工程的价值不只是“多记一点上下文”,而是把进展变成可被系统持续持有的对象。这样一来,长期执行就不再等于一段脆弱的长对话,而会变成一个可续作、可恢复、可重入的问题求解过程。另一位 AK 选手公开提到的黑板架构、统一调度和长期问题求解引擎,虽然设计理念与我们不同,但从公开描述看,本质上也在做同一件事:让高价值进展不要在执行过程中轻易归零。
3.2 策略工程:让系统知道自己卡在第几阶段
拿到 Shell 还找不到 Flag,和压根没打进去,不该用同一套重试逻辑。
我们目前这套 Orchestrator 架构在第二赛区 B 题上暴露出的核心问题,不是模型没有拿到 Shell,而是系统在已经拿到 Shell 之后,仍按“尚未打通利用链”的逻辑继续调度。这个问题重试次数足够,但系统没有准确识别出自己已经从“利用阶段”进入“后利用定位阶段” 。停损机制一旦看见停滞就整体重启,于是系统把“已打通但未定位目标”和“尚未打通”混为一谈。
工程上要解决的,也就不是简单增加重试次数,而是把停损机制分层化,区分侦察失败、利用失败、后利用失败和目标定位失败;每一类失败都绑定不同的恢复策略。重试也不能只是重跑,而要带着失败信息重跑。
从隔壁选手的公开复盘也可以看出,他们在调度、并发和长期执行维持上做了专门工作。策略工程的价值不在于给 Agent 叠更多规则,而在于把“什么时候该继续、什么时候该换路、什么时候该保活续作”这些高价值判断前移进系统本身。
3.3 执行工程:让工具链和搜索链路稳定适配环境
方向对了还落不了地,很多时候不是推理问题,而是脚本、路径库和环境适配没跟上。
比赛数据显示,模型通常偏好 curl 和自写 Python 这类轻量工具,但真正的挑战不在于“用什么工具”,而在于工具调用链路能否在不同环境里稳定适配。后利用阶段如果只有硬编码路径列表,没有按容器类型、运行时、数据库、环境变量、启动参数展开的搜索策略库,就很容易把已经拿到的进展消耗在最后一公里。
因此,执行工程的重点不是堆更多工具,而是补足可复用的环境适配与后利用搜索能力,让系统在“已知方向正确”的前提下把执行做实。
3.4 工程优先级:先补什么,再补什么
先别什么都补,先保进展,再学会换策略,最后再补大而全的工具库。
从投入产出比看,这三类工程问题并不是并列的。
- 优先补状态持久化、幂等续作、失败携带重试,让系统先学会“尽量不要把已经得到的进展弄丢”。
- 其次把停损机制做成分阶段策略引擎,再叠加更强的环境适配与后利用搜索库,让系统从“能跑”逐步走向“能稳定收尾”。
- 短期内仍然难解的问题,则是开放环境中的高质量世界模型构建、长链任务中的低成本全局规划,以及在不引入过高开销的前提下识别自旋、漂移和伪进展。
自动化渗透赛测到的,不只是模型会不会推理,而是一个复合系统能否在压力条件下,把正确方向相对稳定地转化为结果。所谓自主,也不意味着把人的经验完全拿掉,而是把人的判断前移到赛前的架构、调度规则、停损条件和状态设计里。从专用 Agent 开发的视角看,这意味着不适合再把系统理解为一个“万能 Agent + 若干工具”的松散组合,而更适合把高频任务阶段拆成更明确的能力单元,把状态、策略和工具都做成领域内建件。
写在最后
这不只是安全比赛的问题,凡是要多轮执行的 Agent,都可能撞上同样的墙。
前文反复提到的这些问题,例如状态在跨轮过程中丢失、系统误判当前阶段、失败后沿着同一路径重复重试,以及工具与搜索链路在环境变化下不够稳定,并非渗透场景独有。凡是需要多轮执行、外部工具调用、状态跨步保存、失败后恢复的 Agent 系统,无论是代码修复、数据分析、销售流程自动化还是企业运维,都会遇到类似约束:不是不会开始,而是难以稳定收尾;不是缺少单步能力,而是缺少跨步一致性;不是没有找到方向,而是无法把方向沉淀为可复用策略。
这篇文章的结论可以压成三点:
- 当前 Agent 的主要瓶颈,不在“不会推理”,而在“工程链路还托不住推理”。
- 自动化系统里最昂贵的失败,不是没有想到,而是已经想到之后,仍然一次又一次以同样方式失败。
- 所谓自主,不是把人的经验拿掉,而是把人的经验前移到架构、调度、停损和状态设计里。
在禁止人工介入的环境里,系统一旦拿到关键进展,后续链路就要能继续把这段进展推进到结果;系统一旦走错,恢复机制也要能低成本纠偏。 否则,单次推理再精彩,也很难稳定转化为结果。
欢迎关注凌武科技技术博客,查看更多安全研究与工程实践内容:
链接:凌武科技技术博客