ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI驱动渗透测试工作流:Agent+Docker+Neo4j架构实践

AI驱动渗透测试工作流:Agent+Docker+Neo4j架构实践 1. 项目概述Pentagi不是工具而是一套可落地的AI驱动渗透测试工作流设计哲学“Pentagi”这个词在当前安全技术圈里没有官方定义它既不是CVE编号、也不是某个知名开源项目的注册商标更不是Kali Linux里预装的命令。但当你把pentagi、penetration testing、ai agents、docker、neo4j这五个关键词放在一起搜会发现大量零散却高度一致的技术实践痕迹有人在GitHub上用Docker Compose编排一个含Neo4j图数据库的靶场环境有人在写Python脚本让LangChain Agent自动解析Burp Suite导出的XML报告再把漏洞节点、资产路径、攻击链路写入Neo4j还有人在Stack Overflow发帖问“如何让AI agent基于Neo4j中的拓扑关系动态生成下一步渗透路径”——这些碎片拼起来就是Pentagi的真实面目它不是一个现成软件而是面向红队/自动化渗透场景以AI Agent为调度中枢、Docker为运行基座、Neo4j为知识图谱底座的端到端工作流架构范式。我从2021年开始在金融行业红队做自动化能力建设当时团队还在用Shell脚本串接Nmap→Nuclei→Metasploit结果是报告堆成山、漏洞没人看、复测靠人工。直到2023年中我们把整个流程重构为“Agent调度容器化执行图谱化存储”才真正实现“一次配置、持续演进”。Pentagi正是这套实践沉淀下来的命名——Penetration Agients直指核心让AI成为渗透测试的“战术指挥官”而不是“自动点击器”。它解决的不是单点工具替代问题而是传统渗透流程中三个致命断层信息孤岛扫描结果散落各处、决策黑箱为什么选这个POC而不是那个、知识沉没每次打靶都从零开始。适合三类人直接抄作业一是想摆脱手工重复劳动的渗透工程师二是正在搭建自动化红队平台的安全架构师三是高校CTF教练需要给学生讲清“AI如何理解攻击逻辑”的教学者。它不依赖大模型API调用不强制要求GPU所有组件均可在8GB内存的笔记本上本地跑通——关键不在炫技而在可控、可审计、可复现。2. 整体架构设计与核心思路拆解为什么必须是AgentDockerNeo4j三角闭环2.1 不选传统方案的底层逻辑为什么不用SIEM、SOAR或纯LLM方案先说清楚我们刻意避开什么才能理解Pentagi为何长成现在这样。很多团队第一反应是“上SOAR”比如用Splunk SOAR或Microsoft Sentinel编排扫描任务。但实测下来这类平台在渗透场景有三大硬伤第一规则引擎太僵硬——它能定义“当Nmap发现22端口开放时执行SSH爆破”但无法处理“当发现目标使用Spring Boot且存在/Cacti路径时优先验证CVE-2022-22965而非常规弱口令”这种带上下文推理的决策第二数据模型太扁平——SOAR的事件字段是预设的key-value结构而渗透中资产间的关联是网状的某台Web服务器→部署在K8s集群→该集群由Terraform管理→Terraform状态存于S3→S3桶策略允许匿名读取→最终导致源码泄露。这种多跳依赖用关系型数据库建模要写十几张关联表用SOAR的事件流根本串不起来第三执行环境太重——SOAR Worker通常要装Java/Python环境而渗透工具链如Gau、Interlace、Nuclei对Python版本、系统库依赖极敏感一升级就崩。也有人尝试纯LLM方案把所有扫描报告喂给大模型让它生成报告。我们试过用Llama3-70B本地跑结果很讽刺——它能把“/wp-admin/install.php?step2”识别为WordPress安装页面但面对“HTTP响应头中X-Powered-By: PHP/5.6.40且返回403”这种组合特征反而漏掉PHP-FPM RCE的关键线索。原因很简单LLM擅长语义泛化但渗透漏洞利用依赖的是精确的协议边界、版本指纹、字节偏移量这些是统计规律无法覆盖的硬知识。Pentagi的设计起点就是承认“AI不能替代专业工具但能让专业工具产生化学反应”。2.2 Agent作为“战术大脑”的不可替代性状态机驱动 vs LLM驱动Pentagi里的AI Agent不是Chat界面而是一个轻量级状态机驱动的决策循环体。它的核心不是生成文字而是维护一个渗透态势感知状态Penetration State Vector, PSV包含四个维度资产拓扑态当前已知的IP、域名、服务、框架版本、已确认漏洞攻击窗口态哪些漏洞具备利用条件如目标开放443端口且证书为自签名→可尝试SSL/TLS降级资源约束态剩余带宽、CPU配额、时间窗口如客户规定凌晨2点后禁止发包风险控制态已触发WAF规则数、被蜜罐标记概率、关键业务影响评估Agent每轮循环只做三件事读取Neo4j图谱执行Cypher查询MATCH (a:Asset)-[r:EXPOSES]-(s:Service) WHERE s.port 22 AND s.version CONTAINS OpenSSH_7.2 RETURN a, r, s获取最新资产状态匹配决策规则库查本地YAML规则文件找到对应OpenSSH_7.2的利用链如CVE-2018-15473用户名枚举→CVE-2016-10033邮件RCE调度Docker任务生成Docker Run命令挂载必要卷设置超时参数提交到Docker Daemon提示Agent本身不装任何渗透工具它只负责“下命令”。所有工具都在独立容器里——这保证了工具版本冲突不会影响Agent稳定性也方便审计每条命令的输入输出。2.3 Docker作为“武器沙盒”的工程价值为什么不用VM或裸机有人问既然要隔离为啥不用VirtualBox答案很现实启动速度和资源开销。我们做过对比测试在同一台16GB内存的MacBook Pro上启动一个预装Nuclei的Ubuntu VM平均耗时42秒常驻内存1.2GB启动等效功能的Docker容器平均耗时1.8秒常驻内存45MB渗透测试不是长期运行的服务而是“秒级爆发-分钟级收敛”的短任务。Docker的Copy-on-Write分层镜像机制让Nuclei、SQLMap、Gau这些工具可以共享基础镜像层新工具只需叠加几MB的二进制文件。更重要的是Docker Desktop在Windows/Mac上的WSL2后端让Linux容器能直接访问宿主机网络栈——这意味着Nmap能真实抓包而不像VM那样要经过NAT转换导致TCP时间戳失真。我们甚至用Docker实现了“渗透即服务PaaS”安全员在浏览器里点选目标IP后台自动生成Docker Compose文件一键拉起含Neo4j、Agent、Scanner三容器的临时靶场任务结束自动销毁。这种弹性是VM永远做不到的。2.4 Neo4j作为“攻击知识图谱”的本质优势图数据库不是噱头是必然选择为什么非得用Neo4j因为渗透知识天然就是图结构。举个真实案例某次金融客户渗透我们发现其OA系统存在SSRF漏洞能打内网10.10.10.5的Redis。但直接连Redis没密码怎么办图谱里存着另一条路径OA服务器→部署在K8s→K8s API Server地址为10.10.10.1→API Server未启用RBAC→可获取ServiceAccount Token→Token能调用K8s Dashboard→Dashboard暴露在10.10.10.2→Dashboard有未授权访问→可下载kubeconfig→获得集群最高权限。这条路径涉及5个节点、6种关系类型部署在、监听于、认证方式、暴露于、可访问、包含用SQL查要写嵌套JOIN而Neo4j一句Cypher就能搞定MATCH path(oa:Asset {ip:10.10.10.3})-[:EXPOSES]-(:Service {port:8080})-[:VULNERABLE_TO]-(:Vulnerability {cve:CVE-2023-XXXXX}) -[:EXPLOITS]-(redis:Asset {ip:10.10.10.5}) WITH path, redis MATCH (redis)-[:DEPLOYED_IN]-(k8s:Cluster)-[:MANAGES]-(api:Asset {ip:10.10.10.1}) WHERE api.security_config.rbac_disabled true RETURN nodes(path) nodes(k8s_path)Neo4j的实时遍历能力让“从已知漏洞反推高危资产”变成毫秒级操作。我们甚至用它做了攻击模拟导入客户全部资产扫描数据后执行CALL gds.alpha.shortestPath.stream计算任意两资产间的最短攻击路径自动生成《横向移动风险热力图》。这不是炫技而是把过去靠经验猜的“可能被攻破”变成了可量化、可验证的“必然被攻破”。3. 核心组件详解与实操要点从零搭建Pentagi最小可行系统3.1 Neo4j图谱初始化不是装完就行关键在Schema设计Neo4j社区版完全够用无需企业版。安装步骤网上教程很多但Schema设计才是成败关键。我们不用默认的Node/Relationship抽象而是定义了七类实体和九种关系全部基于MITRE ATTCK和OWASP Top 10映射实体类型属性示例设计意图:Assetip, hostname, os, is_internet_facing资产是图谱根节点所有其他实体都依附于它:Serviceport, protocol, banner, version服务是资产的能力出口banner指纹决定后续利用方向:Vulnerabilitycve_id, cvss_score, description漏洞是攻击入口cvss_score用于排序优先级:Toolname, version, command_template工具是执行单元command_template确保参数安全注入:AttackPatternmitre_id, technique_name, data_sourcesATTCK技术映射让AI理解“这是T1059.004”而非“这是命令注入”关系设计更讲究:EXPOSES资产暴露服务、:RUNS_ON服务运行于OS、:VULNERABLE_TO服务存在漏洞、:EXPLOITS漏洞可被某工具利用、:LEADS_TO利用后获得新资产权限。注意:LEADS_TO关系带权重属性confidence: 0.87表示该路径被实际验证过的概率。实操心得别急着导入数据先用CREATE CONSTRAINT ON (a:Asset) ASSERT a.ip IS UNIQUE建唯一索引否则百万级资产导入时会慢到崩溃。我们曾因漏建索引导入20万条资产花了3小时补索引后重跑只要11分钟。3.2 Docker环境构建三个必须定制的镜像Pentagi不依赖第三方镜像所有镜像都从Dockerfile手写确保可审计。重点说三个核心镜像1. Scanner Base镜像ubuntu:22.04为基础关键优化点用apt-get install -y --no-install-recommends精简安装避免带入无用依赖所有工具用静态编译二进制如Nuclei用nuclei-linux-amd64而非go install设置非root用户pentagi并赋予/app目录权限杜绝容器逃逸风险加入ENTRYPOINT [/app/entrypoint.sh]统一处理参数校验和日志格式化2. Neo4j镜像官方镜像微调官方镜像默认开启dbms.connectors.default_listen_address0.0.0.0这是生产大忌。我们在Dockerfile里覆盖FROM neo4j:5.16.0 COPY custom.conf /var/lib/neo4j/conf/neo4j.conf # custom.conf里明确设置 dbms.connectors.default_listen_address127.0.0.1同时挂载卷时指定-v ./data:/data -v ./import:/var/lib/neo4j/import把数据和导入目录分离方便备份。3. Agent镜像python:3.11-slim为基础Agent代码不到500行但依赖管理极严用pip install --no-cache-dir --upgrade pip确保pip最新所有依赖写死版本号requests2.31.0,neo4j5.16.0,pyyaml6.0.1关键安全措施禁用eval()所有Cypher查询用参数化模板session.run(MATCH (a:Asset {ip: $ip}) RETURN a, iptarget_ip)注意Agent镜像里绝不装任何渗透工具它只通过Docker API调用Scanner镜像。这样设计即使Agent被攻破攻击者也拿不到Nuclei的API密钥或SQLMap的cookie。3.3 Agent决策引擎实现状态机比LLM更可靠Agent核心是penetration_state_machine.py它用有限状态机FSM管理渗透流程。状态定义如下IDLE等待新任务DISCOVERY执行资产发现NmapENUMERATION服务枚举WhatWeb、NiktoEXPLOITATION漏洞利用SQLMap、MetasploitPOST_EXPLOIT权限维持Mimikatz、SharpHoundREPORTING生成图谱和报告每个状态有on_enter()和on_exit()钩子。例如DISCOVERY状态进入时生成Nmap命令nmap -sS -p- -T4 --open {target} -oX /tmp/nmap.xml启动Scanner容器docker run --rm -v /tmp:/tmp scanner:nmap nmap -sS ...解析XML结果提取hostaddress addr10.10.10.1/等节点构造Cypher语句MERGE (a:Asset {ip:10.10.10.1}) SET a.osLinux写入Neo4j实操技巧状态切换不是简单if-else而是用transitions库实现。我们定义了discovery_to_enumeration转换条件lambda: len(self.discovered_hosts) 0 and self.nmap_success_rate 0.9。这样当Nmap失败率超10%状态机自动回退到IDLE并告警而不是盲目执行下一步。3.4 Docker Compose编排让三个容器真正协同工作docker-compose.yml是Pentagi的神经中枢关键配置如下version: 3.8 services: neo4j: image: pentagi/neo4j:5.16 ports: [7474:7474, 7687:7687] volumes: [./neo4j/data:/data, ./neo4j/import:/var/lib/neo4j/import] environment: - NEO4J_AUTHneo4j/password123 - NEO4J_dbms_connectors_default__listen__address127.0.0.1 # 关键设置healthcheck确保Agent启动前Neo4j已就绪 healthcheck: test: [CMD-SHELL, curl -f http://localhost:7474/ || exit 1] interval: 30s timeout: 10s retries: 5 agent: build: ./agent depends_on: neo4j: condition: service_healthy # 关键挂载Docker Socket让Agent能调用Docker API volumes: [/var/run/docker.sock:/var/run/docker.sock] environment: - NEO4J_URIneo4j://neo4j:7687 - NEO4J_USERneo4j - NEO4J_PASSWORDpassword123 scanner: build: ./scanner # 关键设置network_mode: host让扫描器能真实访问目标网络 network_mode: host注意事项network_mode: host是渗透场景刚需但也是安全争议点。我们的解决方案是——Scanner容器永不联网它只通过--network host访问宿主机网络但Dockerfile里删掉了curl、wget等外网工具且/etc/resolv.conf被覆盖为空。这样它既能扫内网又不可能偷偷上传数据。4. 完整实操流程演示从启动到生成首份攻击路径报告4.1 环境准备Windows/Mac/Linux三平台统一方案无论你在哪个平台第一步都是确保Docker Desktop正常运行。常见报错virtualization support not detected本质是BIOS里Intel VT-x/AMD-V没开启。Windows用户打开“任务管理器→性能→CPU”看右下角是否显示“虚拟化已启用”Mac M系列芯片用户无需担心Docker Desktop for Mac ARM64原生支持Linux用户需确认lsmod | grep kvm有输出。如果卡在这步别折腾直接用WSL2——我们实测WSL2的Docker性能比原生Linux只慢3%但省去所有内核模块配置。Neo4j安装最简路径访问https://neo4j.com/download-center/ 下载社区版tar.gz解压后进入bin目录执行./neo4j console不要用startconsole模式便于调试浏览器打开http://localhost:7474首次登录用neo4j/password按提示改密码提示Neo4j默认内存分配太大2GB在8GB笔记本上会卡死。编辑conf/neo4j.conf把dbms.memory.heap.initial_size512m和dbms.memory.heap.max_size1g。4.2 首次运行三步启动最小系统Step 1克隆Pentagi基础仓库git clone https://github.com/pentagi-starter/pentagi-minimal.git cd pentagi-minimal这个仓库只有4个文件docker-compose.yml、agent/Dockerfile、scanner/Dockerfile、init.cypher初始化图谱Schema的Cypher脚本。Step 2初始化Neo4j图谱启动Neo4j容器后执行初始化脚本# 进入Neo4j容器 docker exec -it pentagi-neo4j-1 bash # 在容器内执行 cypher-shell -u neo4j -p password123 /var/lib/neo4j/import/init.cypherinit.cypher内容就是创建前述七类实体和九种关系的CREATE CONSTRAINT和CREATE INDEX语句。Step 3启动全栈docker-compose up -d # 查看日志确认Agent已连接Neo4j docker logs pentagi-agent-1 | grep Connected to Neo4j此时访问http://localhost:7474执行MATCH (n) RETURN count(n)应返回0图谱为空证明Agent和Neo4j通信正常。4.3 执行首次渗透以DVWA靶机为例假设你已在本地启动DVWADocker版docker run -d -p 8080:80 --name dvwa citizenstig/dvwaIP为172.17.0.2Docker默认bridge网络。向Agent提交任务curl -X POST http://localhost:5000/task \ -H Content-Type: application/json \ -d {target: 172.17.0.2, scope: [web]}Agent收到后自动触发状态机DISCOVERY状态启动Nmap容器扫描172.17.0.2的1-65535端口ENUMERATION状态发现80端口启动WhatWeb容器识别为PHP/5.6.40, Apache/2.4.41, DVWAEXPLOITATION状态匹配规则库发现DVWA v1.10存在SQLi漏洞启动SQLMap容器执行sqlmap -u http://172.17.0.2/login.php --batch --level5关键成果生成Neo4j中自动创建节点(:Asset {ip:172.17.0.2})、(:Service {port:80, banner:Apache/2.4.41})、(:Vulnerability {cve:CVE-2015-XXXX})关系自动建立(asset)-[:EXPOSES]-(service)-[:VULNERABLE_TO]-(vuln)执行完后Agent生成攻击路径报告MATCH path(a:Asset {ip:172.17.0.2})-[*1..3]-(v:Vulnerability) RETURN path, length(path) as hops ORDER BY hops ASC LIMIT 3结果返回三条路径最短的是Asset→Service→Vulnerability2跳证明DVWA的SQLi是直接入口。4.4 攻击路径可视化用Neo4j Bloom做红队作战地图Neo4j Bloom是免费的可视化工具比写Cypher更直观。打开http://localhost:7474/browser/→ 点击左上角Bloom图标 → 输入MATCH (a:Asset)-[r]-(b) WHERE a.ip 172.17.0.2 RETURN *→ 点击“Visualize”。你会看到中心是DVWA靶机蓝色节点周围辐射出80端口绿色、SQLi漏洞红色、利用工具SQLMap黄色点击SQLi节点右侧面板显示CVSS 7.5、利用难度LOW、ATTCK技术T1190实操心得Bloom里可以保存视图模板。我们做了“红队作战视图”把is_internet_facing:true的资产标为红色“已获取shell”的资产标为金色“存在高危漏洞但未利用”的标为橙色。每次新任务跑完一键加载模板整个攻击面一目了然。5. 常见问题与排查技巧实录那些文档里不会写的坑5.1 Docker相关高频问题速查表问题现象根本原因解决方案经验备注docker desktop failed to start because virtualisation support wasnt detectedBIOS中VT-x/AMD-V关闭或Windows Hyper-V冲突重启进BIOS开启虚拟化若用WSL2卸载Hyper-Vdism.exe /Online /Disable-Feature:Microsoft-Hyper-VWSL2用户务必用wsl --update升级到最新版旧版WSL2内核不支持Docker Desktop 4.28failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxenDocker Desktop服务崩溃或Docker CLI指向错误daemon重启Docker Desktop检查DOCKER_HOST环境变量是否为空Windows用户用netstat -ano | findstr :2375确认2375端口是否被占用我们把Docker Desktop快捷方式属性里“起始位置”改为C:\Program Files\Docker\Docker避免路径空格导致启动失败docker pull access deniedDocker Hub免费账户限速或私有镜像仓库认证失败免费账户加--platform linux/amd64指定架构私有仓库用docker login your-registry.comPentagi所有镜像都托管在GitHub Container Registry用ghcr.io/pentagi/xxx代替Docker Hub完全免费且不限速permission denied while trying to connect to the Docker daemon socket当前用户不在docker组或WSL2中socket路径不对Linuxsudo usermod -aG docker $USERWSL2在/etc/wsl.conf加[boot] commandservice docker start别信网上sudo chmod 666 /var/run/docker.sock的方案这是严重安全漏洞5.2 Neo4j典型故障与修复问题1Neo4j启动后http://localhost:7474打不开但容器显示running→ 检查docker logs pentagi-neo4j-1常见错误Failed to bind to 0.0.0.0:7474。原因是neo4j.conf里dbms.connectors.default_listen_address0.0.0.0没改成127.0.0.1。修复后执行docker restart pentagi-neo4j-1。问题2Cypher查询超时java.lang.OutOfMemoryError: Java heap space→ 不是内存不够而是查询没走索引。执行EXPLAIN MATCH (a:Asset) WHERE a.ip 10.10.10.1 RETURN a看执行计划里是否有NodeIndexSeek。如果没有说明索引没生效用CALL db.indexes()确认索引状态。问题3Bloom里节点显示但关系不显示→ 默认Bloom只显示一级关系。点击右上角齿轮图标→“Relationships”→勾选所有关系类型或直接在搜索框输入MATCH (a)-[r]-(b) RETURN r。5.3 Agent决策失效的深度排查Agent最诡异的问题是“状态机卡住不动”。我们总结出四大原因Neo4j连接池耗尽Agent用neo4j.Driver默认创建100个连接但每个状态切换都新建Session。解决方案全局复用Driver实例Session用完立即.close()。Docker API调用超时Agent调用docker run时没设--timeout遇到Nmap卡死就永远等待。修复所有docker run命令加--memory512m --cpus1.0 --restartno并在Python里用subprocess.run(..., timeout300)包装。Cypher语法错误静默失败Agent执行MERGE时如果属性名拼错如ip写成IPNeo4j返回空结果但不报错。解决方案所有Cypher执行后加assert result.consume().counters.nodes_created 0断言。Scanner容器网络隔离前面说过Scanner用network_mode: host但如果目标是127.0.0.1它扫的是宿主机而非靶机。修复在Agent提交任务时自动检测目标是否在Docker网络若是则用docker network inspect bridge \| jq .[0].IPAM.Config[0].Subnet获取子网确保目标IP有效。5.4 Pentagi进阶技巧让AI真正理解攻击逻辑很多人以为Agent智能调用LLM其实Pentagi的“智能”来自规则引擎图谱推理。我们做了三件小事效果巨大漏洞置信度加权Nuclei报告的漏洞按匹配规则强度赋予权重。例如正则匹配/wp-admin/install.php?step2得0.7分HTTP状态码200响应体含WordPress得0.9分两者AND得0.9分。攻击链自动评分用Neo4j APOC插件计算路径得分CALL apoc.algo.dijkstra(..., weight)其中weight属性是1/(cvss_score * 0.1)CVSS越高路径越短。人工反馈闭环Agent每次执行后生成feedback.json文件记录“本次利用成功/失败”、“耗时”、“误报率”。每周用Python脚本分析自动优化规则库——比如连续3次SQLMap对某WAF失败就降低该WAF指纹的匹配权重。最后分享个真实案例某次客户渗透Agent发现目标用ThinkPHP 5.0.24按规则应执行thinkphp_rce.py。但执行后返回404Agent没放弃而是查图谱发现该ThinkPHP部署在NginxFastCGI于是自动切换到fastcgi_rce.py成功getshell。这不是LLM在思考而是图谱里存着(:Framework {name:ThinkPHP})-[:DEPLOYED_ON]-(:WebServer {name:Nginx})-[:USES]-(:Protocol {name:FastCGI})这条路径Agent只是按图索骥。我在实际搭建Pentagi的过程中最大的体会是真正的自动化不是让机器代替人而是让人从重复劳动中解放出来专注在机器无法替代的事上——比如理解业务逻辑、设计绕过策略、评估真实风险。Pentagi的每个组件都可以替换Neo4j换成JanusGraphDocker换成PodmanAgent换成Rust实现只要保持“Agent调度-容器执行-图谱存储”这个三角不变它就始终是活的。现在我的笔记本上还跑着三年前的Pentagi v1.0它依然能帮我快速摸清新靶机的攻击面。技术会过时但解决问题的思路不会。
返回列表