arxiv 把渗透测试拆成 pytest 能断言的子任务:Google 式记分法轮到防守方用了

简介: 本文提出将LLM渗透测试能力量化为可执行的pytest回归基线,首创“攻击链子任务记分法”(侦察、入口、提权等7项0/1/2分级),突破传统二元报告局限。通过每周自动化运行,使防守方提前数周感知能力增长趋势,实现从“事后响应”到“事前加固”的范式升级。

arxiv 在 2026-09-09 挂出一篇论文:《Big Enough to Break Out: Tracking the Rising Capability of LLM Penetration-Testing Agents》(arxiv 2609.10780)。它的对比实验表面上是一个标准的「新模型更强」故事:旧版基于 PentestGPT 的人在环系统(跑开源权重 Kimi K2.5,普通大学 GPU,无 provider 护栏)在 3 个公开靶场里 2 个没走到终点;新版全自主系统(跑 Claude Opus 4.8)把 3 个靶场全部解出。

但作者把记分方式换成「攻击链子任务清单」之后,另一条事实浮了出来:人在环系统在没走通的靶场里,已经完成了约一半的子任务。

这个「约一半」的信息量比「全破」更大。只看二元结论,防守方看到的是某一天「攻击者得手了」;看子任务记分,看到的是一条曲线——它今天已经能走通侦察、入口、漏洞识别,剩下的一半只差最后一推。作者明说这套记分法防守方拿去可用:在能力增长的时候就度量它,而不是到实战里才遇到它。

这篇文章讲一个工程动作:把渗透测试智能体的攻击能力,写成一条 pytest 能跑的每周安全回归基线。

一、先给结论:这篇论文最该抄走的不是结论,是记分表
渗透报告的惯例结论是二元加定级:拿下或没拿下,高危中危低危。这份报告回答的是「这次演了什么」,回答不了「对手正在变成什么」。子任务记分把一次事件变成一张清单:攻击链拆成侦察、入口打点、漏洞识别、权限提升、横向移动、数据导出、清理痕迹,每一项独立记分。清单一旦存在,它就自然变成回归基线——这正好是测试工程师的主场。

二、锚回旧知识:这就是接口测试的断言粒度问题
先给结论:整个事务只断言 HTTP 200,等于没断言;攻击链只断言『有没有被拿下』,等于没度量。

你在接口测试里早就学过这一课。一个下单事务,只断言状态码 200,库存扣没扣、优惠券核销没核销、对账消息发没发全看不见——线上出事故时你会发现 200 的响应照样带着三个坏断言。后来你学会把断言铺到每个业务不变量上,测试才第一次有了「预警」能力。

二元渗透报告和「只断言 200」是同一种病:把多阶段过程压成一个终态布尔值。论文里人在环系统那两个「没走完」的靶场就是证据——终点没到,但链路走了一半,这一半在二元报告里是零信息,在子任务记分里是一条正在爬升的曲线。

三、论文两系统对照,以及另外两句提醒
对照维度
人在环旧系统
自主新系统
测试侧启示
系统构成
PentestGPT + 人在环 + 开源权重 Kimi K2.5
PentestGPT 基础上的自主系统 + Claude Opus 4.8
被测的是「系统」不是「模型」:脚手架、自主度、记忆架构全在测量范围内
运行环境
普通大学 GPU,无 provider 护栏
摘要未展开,本文不猜
环境是被测对象的一部分,报告口径里不能静默省略
靶场完成度
3 个公开靶场中 2 个未走完
3 个全部解出
二元结论只能告诉你「已经发生了什么」
子任务完成度
未走完的靶场完成约一半子任务
全链路走通
「约一半」才是预警信号:全破之前,增长早就可见了

论文里还有两句容易被划过去的话,都值得测试工程师抄进自己的规范。第一句是作者自己声明的归因限制:模型、脚手架、自主度、记忆架构同时变了,无法归因。这等于承认这是一次「多变量同改的对比实验」——恰好是回归测试纪律的反面教材。你把记分基线搬回防守侧时,第一准则就应该是每轮只动一个变量,否则曲线涨了你也说不清是谁的功劳。第二句关于记忆:作者给系统加了一个 coverage-memory 层,两套系统的表现都没有改善,卡点更像「规划与推进」而不是「记忆丢失」。防守启示是别把筹码押在单点上——你堵住了入口,不代表它的规划能力不会在下一次周度回归里把提权那段补分。

四、动作一:把攻击链拆成一张可记分的 yaml 清单
记分要成立,子任务清单必须先写死——每一项有防守断言、有记分口径,不允许「感觉挡没挡住」。

attack_chain_scorecard.yaml —— 攻击链子任务记分表(本文示例口径)

记分规则:每个子任务 0/1/2 —— 0 防线完好;1 部分触及(命中但未拦截等中间态);2 攻击方得手

chain:
-id:recon
name:侦察与信息收集
defense_assert:对外暴露面与指纹泄漏扫描,无未登记端口/服务
score_rule:"0=无未授权暴露;1=暴露面扩大但未泄漏有效信息;2=攻击方拿到可用资产清单"
-id:entry
name:入口打点
defense_assert:探针载荷被WAF/IPS命中并拦截(不是只告警)
score_rule:"0=命中且拦截;1=命中但仅告警放行;2=打点成功"
-id:vulnid
name:漏洞识别
defense_assert:SCA依赖清单与生产实际版本一致,无幽灵依赖
score_rule:"0=清单一致;1=有滞后但滞后项不可达;2=滞后项构成可用入口"
-id:privesc
name:权限提升
defense_assert:服务账号凭据文件权限不严于0600即告警;sudo配置无免密通配
score_rule:"0=两项全过;1=一项越线;2=可稳定提权"
-id:lateral
name:横向移动
defense_assert:东西向防火墙白名单生效,跨网段可达性探测必须失败
score_rule:"0=探测全失败;1=存在可达但被认证挡住;2=可达且可认证"
-id:exfil
name:数据导出
defense_assert:出口DLP特征库为当期版本;大批量异常出口在5分钟内出告警
score_rule:"0=库新且告警达标;1=滞后一个周期内;2=可静默导出"
-id:cleanup
name:清理痕迹
defense_assert:审计日志实时集中采集;本地日志删除/异常轮转同样触发告警
score_rule:"0=删日志必告警;1=有采集有延迟;2=可无痕清理"
为什么这么写、踩过什么坑。 第一,记分用 0/1/2 三档而不是二元过/不过。论文里「约一半」之所以有价值,就是因为存在「部分进展」这个中间态;你把防守也记分成二元,等于自己把曲线拍平了。第二,每条 score_rule 必须写到「机器可判」的程度——「权限不严于 0600 即告警」这种表述可以直接翻译成断言,「凭据管理良好」不行;凡是只能靠人眼读的断言,第三周开始就没人认真看了。第三,cleanup 这条最容易被省略,但它恰是智能体最可能超出人类习惯的一环:它的「推进规划」如果包含清痕迹,说明链路已走到很深处,这一项从 0 变 1 值得立刻拉响内部预警。

五、动作二:每个子任务落一条可验证的防守断言

tests/security/test_attack_chain_weekly.py —— 每周把七条断言全跑一遍

import pathlib
import pytest
import yaml

CHAIN = yaml.safe_load(
pathlib.Path("attack_chain_scorecard.yaml").read_text(encoding="utf-8"))["chain"]

—— 每条检查函数只做一件事:返回 0/1/2 分,判定逻辑来自 yaml 的 score_rule ——

def check_recon(env): ... # 对比上次登记的暴露面快照,返回增量
def check_entry(env): ... # 打探针载荷,确认 WAF 日志里是 block 不是 alert
def check_vulnid(env): ... # SCA 清单与生产版本比对,找出幽灵依赖
def check_privesc(env): ... # stat 凭据文件 mode 位 + 解析 sudoers
def check_lateral(env): ... # 从低敏网段发起跨段探测,期望全部失败
def check_exfil(env): ... # DLP 特征库版本比对 + 合成批量出口测告警时效
def check_cleanup(env): ... # 注入一次本地删日志动作,确认告警会响

CHECKS = {"recon": check_recon, "entry": check_entry, "vulnid": check_vulnid,
"privesc": check_privesc, "lateral": check_lateral,
"exfil": check_exfil, "cleanup": check_cleanup}

@pytest.mark.parametrize("task", CHAIN, ids=lambda t: t["id"])
def test_subtask_defense(task, env, score_recorder):
got = CHECKStask["id"] # 0/1/2
score_recorder.record(task["id"], got) # 无论几分都记进本周账
assert got < 2, f"[{task['id']}] {task['name']} 防线被穿透。记分口径:{task['score_rule']}"
为什么这么写、踩过什么坑。 第一,注意 record 发生在 assert 之前——记分曲线要收录「部分得分」的周次,断言只兜「被穿透」的底线。如果只在失败时记录,你会重蹈二元报告的覆辙:曲线全是零分和一分的锯齿,看不到缓慢爬升。第二,断言消息里带上 yaml 的记分口径,让 CI 红了之后的第一读者(值班同学)不需要再翻文档就知道该去修哪条防线——这就是「修复指引」维度上子任务记分对二元报告的全胜。第三,探测类断言(跨网段可达性、批量出口告警)会真的发包,env 里必须区分靶场环境与生产环境的开关,生产环境只跑被动采集类检查;把主动探测打进生产网的那一次,通常就是这个体系被一刀关停的那一次。

六、动作三:每周跑一次,不管有没有攻防演练

.github/workflows/attack-chain-baseline.yml(片段)

name:attack-chain-weekly-baseline
on:
schedule:
-cron:"0 3 1" # 每周一凌晨 3 点,无人窗口
workflow_dispatch:{} # 攻防演练前后手动加跑一轮
jobs:
score:
runs-on:ubuntu-latest
steps:
-uses:actions/checkout@v4
-uses:actions/setup-python@v5
with:{python-version:"3.11"}
-run:pipinstallpytestpyyaml
-name:Rundefenseassertions
run:pytesttests/security/test_attack_chain_weekly.py-q
--junitxml=reports/chain-score.xml
|tee-areports/chain-weekly.txt
-name:Postscorebacktorepo
run: |
git config user.name "sec-bot"
git add reports/
git diff --cached --quiet || git commit -m "chore(sec): chain score $(date +%F)"
git push
为什么这么写、踩过什么坑。 第一,schedule 才是这套东西的心脏:论文度量的是「能力随时间的增长」,你只有按固定周期采样,pytest 的红绿历史才会连成曲线;只在演练时跑,永远只有离散的几个点。第二,记分结果 commit 回仓库(配 [skip ci] 或按路径过滤防自触发),季度复盘时 git log reports/chain-weekly.txt 就是完整的攻击能力增长档案——和你熟悉的性能基线燃尽图同一个套路,只是横轴从发布次数换成了周次。第三,最大的坑是「断言写完就冻结」。攻击链子任务不是静态的,每季度评审一次清单本身:有没有新的子任务类型值得加行,就像你每季度评审用例集一样。

七、二元结论 vs 子任务记分:哪张表能告诉你下个月会发生什么
对照维度
二元攻防结论报告
子任务记分回归基线
预警提前量
被拿下才知道,永远慢一步
看得见这周哪条子任务多拿了 1 分,比「拿下」早数周
修复指引
「建议加固边界」式泛泛结论,无人知道先修哪
记分卡在 privesc,就去收紧凭据权限——修复直接对应断言
趋势可见性
报告散在各次演练里,没有曲线
每周记一分,pytest 红绿历史天然连成增长曲线
报告成本
每次演练都烧人天,低频
断言一次写成,周度运行的边际成本趋近于零
对照表里最值钱的是第一行和第二行的组合:二元报告给你「事后知情」,记分基线给你「事前议程」——下周例会该修哪条防线,曲线已经替你排好了。

写在最后
这篇论文对防守方的真正礼物,不是「智能体变强了」这个焦虑,而是一套可以立刻搬走的度量方式:把对手的多阶段过程拆成子任务清单,逐项记分,定期采样。它把「威胁什么时候降临」这个无法回答的问题,换成了「本周曲线涨了几分」这个可以回答的问题。

别等渗透报告告诉你『被拿下了』——把攻击链写成断言、把能力增长画成曲线,防守方的复利来自提前量。

相关文章
|
17小时前
|
人工智能 安全 API
不用先学复杂平台:6个步骤把Agent的工具调用、轨迹和结果测清楚
本文揭示Agent测试的核心陷阱:答案正确≠行为可靠。AWS Agent-EvalKit提出Plan-Data-Trace-Run-Eval-Report六阶段评测法,强调通过完整执行轨迹验证工具调用、参数准确、数据忠实与推理连贯性,而非仅检验最终输出。适合测试团队快速落地实践。
|
4天前
|
人工智能 测试技术 API
Agent Skills 到底是什么?测试开发必须搞懂的下一代 AI 能力单元
本文探讨AI测试开发新范式:Prompt已失效,关键在于构建“Skill”——结构化、可复用、带错误处理的原子能力单元。它封装团队真实工作流,与MCP协同解决“能做”与“做对”问题,正成为测试开发核心竞争力。
|
4天前
|
人工智能 监控 测试技术
3个Skills解决SDK版本、代码生成和回归测试,初级测试也能照着做
本文探讨AI编程助手时代测试新挑战:模型可能引用过期文档生成“能跑但错误”的代码。借鉴Google为Gemini设计的Skill评测实践,提出可落地的工作流——通过样本集设计、四维断言(版本/接口/禁用项/可追溯性)、CI化回归测试及三个轻量级Skill切入点,将“知识新鲜度”转化为可量化、可监控的测试能力。
|
3天前
|
前端开发 JavaScript 测试技术
别再写一长串 XPath 了:给登录页写一条扛得住小改版的用例
本文直击应届生UI自动化痛点:用例脆弱易崩。以登录页为例,详解如何用Playwright写出“抗改版”的稳定用例——优先采用语义化定位(role/label),辅以testid兜底;封装自愈定位器实现智能降级;断言聚焦用户可感知的业务结果(URL、文案、状态)。地基打稳,方能长久维护。
|
5天前
|
SQL 人工智能 安全
GitHub AI Scan不再依赖CodeQL默认配置:覆盖扩大后,怎么证明漏洞没漏?
GitHub扩大AI Scan覆盖,无需CodeQL默认配置即可触发扫描。本文详解如何构建可解释漏洞样本、设立误报门禁、开展配置矩阵与稳定性测试,并强调:覆盖提升不等于能力可靠,唯有结合真值集验证、多维指标评估与分层处置,才能确保AI安全扫描真正落地可信。
|
5天前
|
缓存 安全 测试技术
3个Skills把密钥盘点、轮换、撤销串成一条测试流水线
本文探讨GitHub企业凭据治理的测试实践:强调凭据需结构化管理(类型、所有者、使用时间等五要素),构建“发现—确认—轮换—撤销—验证”可回归流程;通过分层验收、行为验证与最小权限测试,确保Agent安全执行任务,并以“使用证明”替代主观判断,实现可信、可审计的凭据生命周期管控。
|
1月前
|
人工智能 JavaScript 测试技术
如果你今年准备找测试开发工作,我建议你认真看看DeepSeek Harness
DeepSeek Harness(dsh)是2026年8月开源的MIT许可Agent框架,以“一切皆插件”为核心,Star超15万。本文提供3个实操项目:实测评估、插件开发、AI/人工用例对比,助测试工程师打造差异化竞争力。
|
13天前
|
人工智能 自然语言处理 前端开发
字节用半年让85%的AI用例跑进CI/CD,你的团队还在为“AI生成不能用”发愁?
本文剖析字节跳动NL2Test Agent成功落地的五大关键:聚焦“用例转译”而非替代、先闭环再优化、LLM与程序分工协作、精准治理上下文、优先生成稳定断言。对比失败案例,揭示AI测试成败核心在工程设计,而非模型能力。
|
1天前
|
人工智能 数据挖掘 Linux
千问办公官网入口:qwenwork.cn (一键直达)注册送2000积分,支持免费使用!
千问办公(QwenWork)是阿里云推出的AI智能办公平台,支持网页端免下载即用,也提供Windows/Mac/Linux客户端。新用户注册送2000积分,个人版免费可用,企业版198元/席/月起。阿里千问办公QwenWork官网:https://t.aliyun.com/U/0VCTGt 阿里AI工作平台,一句话完成数据分析、PPT 生成、视频剪辑、网页搭建等复杂任务
326 1
|
5天前
|
缓存 API 开发工具
保姆级上手|千问大模型 API 接入指南,账号开通、密钥申领与代码调用一步通
千问大模型依托百炼平台提供兼容OpenAI标准的API接口,降低了开发者接入国产大模型的门槛。整个接入链路分为账号实名认证开通服务、生成API‑Key、本地环境配置、接口调试、业务迭代优化几个阶段。普通对话、多轮会话、流式输出、图文多模态都有成熟的代码实现,开发者可以直接复用示例代码快速验证业务想法。选型层面,优先qwen‑plus覆盖绝大多数业务;复杂深度推理选择qwen3.8‑max;高并发轻量化任务使用qwen‑turbo。
268 0

热门文章

最新文章