面向 DeepSeek Harness(dsh)的渗透测试模式 —— 一个记录层 + 执行层合并的自包含插件 bundle:
- 记录层(来自 howmp/dsh-pentest):把一次授权渗透测试建模成一张带语义边的探索链路图(goal → intent → fact → finding + 资产树),并在 Web 中以「探索链路 / 漏洞 / 资产 / 报告」四个视图实时可视化。
- 执行层(本项目自研):5 个薄工具 ——
pentest_arsenal(调 arsenal 容器里的 nmap/nuclei/sqlmap/ysuserial/JNDI/内存马等真实武器)/pentest_scope(授权范围记录)/pentest_bypass(知识懒加载)/pentest_shot(无头浏览器截图 + 原始包取证)/pentest_submit_flag(平台)。由执行子 agent 调用,结果经pentest_submit直写回父 intent。 - 证据与交付:
pentest_evidence_add归档任意来源证据;pentest_topology生成资产拓扑 HTML(探到新资产自动更新);报告嵌入截图与污点路径。
一句话:v0.5 起,记录、执行、可视化形成闭环——记录层管图,执行层不再把武器注册成模型工具,而是由 pentest_arsenal 把探测/利用下沉到 arsenal 容器(Kali + JDK8 + 真实武器库)。
| 面 | 内容 |
|---|---|
| 记录层 | pentest storage-domain(6 表:goals/intents/facts/findings/assets/edges)+ 确定性 id(<kind>-<n>)+ 会话投影纯重放 |
| 执行层 | 4 个薄工具:arsenal(调容器武器)/ scope(门禁)/ bypass(知识懒加载)/ submit_flag(平台)。真实武器在 arsenal 容器里(nmap/nuclei/sqlmap/hydra/msfconsole/ysuserial/JNDIExploit/java-chains) |
| Web 视图 | 探索链路(@xyflow/react 图,边带「意图链/产出/推导自/证实」关系胶囊)、漏洞(严重度/可复现步骤/影响资产)、资产(列表/图)、报告(Markdown 渲染·复制·保存) |
| 编排 | 指挥官(决策 agent)建 goal/intent,执行子 agent 只被授予 pentest_submit + 执行工具,toolFilter.deny 禁掉记录与委派工具 |
| 持久化 | 仅 pentest 域路由到 sqlite($DSH_HOME/storages/pentest-sessions.db),宿主其它域仍走默认 json 后端 |
| 授权 | pentest_add_goal 的 authorization 参数记录授权说明(审计事实,非门禁;扫描/利用仍受部署沙箱与审批约束) |
从本地 tarball 安装:
# 从 Release 装(推荐)
dsh plugin --profile web add https://github.com/hack-umbrella/pipadeep/releases/download/v1.6.1/pipadeep-dsh-pentest-1.6.1.tgz
# 或装本地 tarball
dsh plugin --profile web add -w file:/path/to/pipadeep-dsh-pentest-1.6.1.tgz
-w仅本地 tarball 且 web profile 是 pnpm workspace 根时需要(pnpm 10 要求显式--workspace-root)。
重启 dsh 后,在新会话中选择自动注册的「渗透模式 Pro」。
dsh 0.1.7+ 有插件安装门禁:peer 范围必须能覆盖当前 dsh 版本(按
includePrerelease语义判定)。 自 v1.6.0 起本插件已把 peer 放宽为 caret,可直接安装;更早版本写的是精确版本,会被拒装 (此时只能用dsh plugin allow-version … --accept-risk绕过,不建议)。
- 新会话选择「渗透模式 Pro」预设。
- 用户只需给出目标 + 目的(例如「扫描 10.0.0.5,拿到尽可能多的 flag」)。
- 指挥官(决策 agent)调用
pentest_add_goal起头,随后沿链路推进:建 intent → 委派执行子 agent → 子 agent 用执行工具动手 → 每组确认结果立刻pentest_submit写回 → 派生新 intent 继续。 - 右侧「渗透」标签实时显示探索链路图 / 漏洞 / 资产 / 报告。
- 领域模型(
lib/pentest.js,vendored):storage domainpentest(version 2)——goals / intents / facts / findings / assets / edges六张表。边即链路词汇:spawns(goal→intent)、yields(intent→fact)、derived_from(fact→intent)、proves(intent→finding)、parent(asset→asset)。finding 必填reproducibleSteps(至少一条)。 - 确定性 id:节点/边 id 为
<kind>-<n>(按会话计数),工具返回 id 供模型跨调用引用;会话投影从日志纯重放同一张图,Web 端不读数据库。 - 记录工具(9 个):
pentest_submit/pentest_add_goal/pentest_add_intent/pentest_add_fact/pentest_add_finding/pentest_add_asset/pentest_state/pentest_graph/pentest_report。 - 执行工具(5 个,
lib/pentest-tools.js):pentest_arsenal等价docker exec arsenal arsenal <tool> <args>(需 dsh 宿主可访问 docker);pentest_scope读PENTEST_SCOPE;pentest_bypass读PENTEST_BYPASS_FILE。 - 协议:
pentest:protocol系统提示段(指挥官沿链路推进、子 agent 经pentest_submit直写父 intent、与用户交互一律中文)+tool:pentest-tools速查段(SQLi/LFI/命令注入/上传绕过/Python 沙箱逃逸/flag 位置)。 - Web 视图(
lib/ui-pentest.client.js,vendored):按会话注册(当前会话或祖先链含pentest预设才显示,非渗透会话隐藏);四个子标签。v1.0 起cordis.patch.yml里ui-pentest行改用裸包名@pipadeep/dsh-pentest注册,客户端模块才会被 dsh 的 client-modules 扫描器发现并注入 boot graph(此前子路径名被exactPackageSpecifier拒绝、UI 静默缺失);浏览器半注册 id 亦改为裸包名保持一致。
在 vendored 记录层之上,lib/pentest-tools.js(自研、纯 JS、可改)为 5 个薄工具(对齐 Cairn_Y「模型界面要小,武器进环境」):
pentest_arsenal:调 arsenal 容器武器(docker exec arsenal arsenal <tool> <args>),覆盖 nmap/nuclei/sqlmap/ysuserial/JNDI/内存马/java-chains 等。pentest_scope:查看/检查授权范围(PENTEST_SCOPE),配置后进入工具级门禁。pentest_bypass:读取你的知识库 JSON(PENTEST_BYPASS_FILE,绕过手法/PoC/技巧),按需返回。pentest_shot(v1.2.0):本机无头浏览器(Playwright/Chrome, headless=new)打开目标并截图取证,默认经 mitmproxy(上游可转发 Burp)把原始请求/响应一并取回,落盘成「截图 +.http原始包 +.shot.mjs可复现脚本」三件套;回传的evidence原样传给pentest_add_finding/pentest_submit,报告自动嵌图。pentest_submit_flag:tsec 平台 flag 提交。
以上薄工具都不打进常驻提示,只在需要时调用,节省每轮上下文 token,给模型留出推理空间。
Playwright(本机 Chrome, headless=new) --proxy--> mitmproxy :8081 --upstream--> Burp :8080 --> 目标
└─ 携带 X-Pentest-Evidence: <runId> └─ 按 runId 落原始请求/响应(证据索引 + HAR)
- 工具:
pentest_shot({ url, findingId?, label?, steps?, fullPage?, headers?, cookies?, proxy? });steps支持goto/fill/click/press/waitForSelector/wait/screenshot/hover/select/evaluate。 - 产出:
$DSH_HOME/storages/evidence/<findingId>/….png | .http | .shot.mjs,evidence数组回传后写进 finding。 - 代理链:工具自动拉起 mitmproxy(
lib/mitm-addon.py按证据头索引原始包),上游默认转发 Burp(PENTEST_SHOT_UPSTREAM可改 / 置空直连);已在跑则不重复启动。 - Web 证据:漏洞 tab 直接显示截图缩略图(经只读路由
/api/pipadeep-pentest/evidence?path=…,限证据目录内);报告 Markdown 嵌入。 - CA:默认
ignoreHTTPSErrors(多层 TLS 直放,渗透场景可接受);需严格校验时把 mitmproxy CA 装进专用 Chrome profile。 - 前提:
npm i -g playwright(+ 本机 Chrome)与brew install mitmproxy;缺失时工具返回明确报错。
| 变量 | 说明 | 默认 |
|---|---|---|
PENTEST_PROXY |
HTTP 代理(host 或 host:port);设 none/off/direct 直连 |
http://127.0.0.1:8080(Burp) |
PENTEST_SCOPE |
授权范围,逗号分隔的域名/IP/CIDR;配置后启用工具级门禁 | 未设置=放行(建议设置) |
PENTEST_BYPASS_FILE |
你的自定义绕过库 JSON 路径 | ./pentest-bypass.json |
PENTEST_SKILLS_DIR |
pentest_skill_add 写入技能目录(dsh 扫描根) |
.dsh/skills |
PENTEST_SHOT_PROXY |
pentest_shot 浏览器代理入口(mitmproxy) |
http://127.0.0.1:8081 |
PENTEST_SHOT_UPSTREAM |
mitmproxy 上游代理(转发 Burp/Yakit);置空=直连 | http://127.0.0.1:8080 |
PENTEST_SHOT_PORT |
mitmproxy 监听端口 | 8081 |
PENTEST_EVIDENCE_DIR |
证据(截图/原始包/脚本)落盘根目录,Web 证据路由只读此目录 | $DSH_HOME/storages/evidence |
PENTEST_PLAYWRIGHT / PENTEST_NODE_PATH |
显式指定 playwright 路径 / 追加 node_modules 搜索路径 | 自动探测 |
插件内置 skills/ 目录(dsh 技能:<name>/SKILL.md,kebab-case 名 + description frontmatter),
包含 pentest-bypass / pentest-recon / pentest-exploit / pentest-report / pentest-methodology 五套技能。
- 按需加载:由
pentest-methodology(指挥官准则)、pentest-bypass(WAF 绕过)、pentest-recon(侦察)、pentest-exploit(利用)、pentest-report(报告)组成,模型匹配到场景才加载正文,不占常驻上下文。 - 自进化:dsh 的
skill-filesystem扫描以下根目录,且编辑技能正文无需重启/缓存失效—— 直接改skills/<name>/SKILL.md即可被后续目录刷新吸收;绕过手法则编辑pentest-bypass.json即时生效。
自带 skills/ 的挂载方式(v1.6.0 起已自动,无需配置):lib/preset-skills.js 在预设作用域内
显式注册这 5 个技能。原因是 dsh 0.1.7 起预设不再是「目录」,预设内 skills/ 失去了被发现
的介质($DSH_HOME/.agent-presets 扫描一并移除);显式注册在两代 dsh 上行为一致,也不依赖
安装路径能被猜到。
更新技能=改
skills/<name>/SKILL.md后重启 dsh(显式注册发生在预设挂载时)。
提供两层:
- 对话式(主推,已可用、可测):
pentest_bypass_list/add/remove、pentest_skill_list/add—— 直接对话即可增删绕过/技能。 - 数据 API(已接线、已测):
lib/bypass-routes.js提供/api/pipadeep-pentest/bypass(GET/POST)、/bypass/remove(POST)、/skills(GET/POST),读写绕过库与技能;已在cordis.patch.yml注册bypass-routes行,供脚本/外部 UI 复用。
图形化「绕过/技能」面板(
ui-pentest-manager.client.js)在 0.4.0 曾并入 client bundle,但二次注册conversation.view槽位会覆盖原有「渗透」面板,已在 0.4.1 回滚移除。后续若要图形面板,需在PentestView内部新增一个 tab(而非第二个 slot),待验证后再加。
插件不自带分离的记忆工具——跨会话记忆交给成熟的 dsh 记忆插件。推荐 dsh-auto-memory(自包含三层记忆:每轮自动沉淀、memory_log/memory_recall/memory_consolidate、低 token、把凭据挡在提示外,无需外部 server):
cd ~/.dsh/profiles/web
pnpm add @a9i5k4/dsh-auto-memory
# 在 package.json 的 dsh.profile.bundles 追加 "@a9i5k4/dsh-auto-memory",然后重启 dsh web- 通用跨会话记忆(经验、约定、教训)→ 交给 dsh-auto-memory。
- 渗透领域技法库 → 本插件的
skills/*/SKILL.md(可编辑、按需加载)+pentest-bypass.json(绕过手法)。 - 避免两套记忆存同一类内容:
skills/pentest-bypass.json是技法知识,auto-memory 是通用记忆,各司其职。
dsh-pentest/ # bundle 根 = 包 @pipadeep/dsh-pentest
├── skills/ # ★ 自进化技能库(<name>/SKILL.md)
│ ├── pentest-bypass/SKILL.md
│ ├── pentest-recon/SKILL.md
│ ├── pentest-exploit/SKILL.md
│ ├── pentest-report/SKILL.md
│ └── pentest-methodology/SKILL.md
├── package.json # bundle manifest:dsh.bundle.patch + dsh.client + exports 子路径
├── cordis.patch.yml # 补丁层:UI、sqlite 后端、storage-domain 路由、preset root
├── lib/
│ ├── pentest-tools.js # ★ 本项目源码:5 个薄执行工具(可直接改,无构建)
│ ├── pentest.js # vendored 自 howmp/dsh-pentest:记录层(领域模型/工具/投影/协议)
│ ├── storage-sqlite.js # vendored:渗透记录专用 sqlite 后端(node:sqlite)
│ ├── ui-pentest.js # vendored:Web 插件宿主半(空 apply)
│ ├── ui-pentest.client.js # vendored:Web 插件浏览器半(4 个子标签,@xyflow/react 内联)
│ ├── preset-root.js # vendored:注册包内只读预设目录
│ ├── index.js # vendored:包入口(空 apply)
│ └── invariant.js # vendored:探索图不变量伴生(生产环境不加载)
├── preset/pentest/ # ★ 「渗透模式 Pro」agent 预设(指挥官 + 执行子 agent)
│ ├── agent.cordis.yml
│ └── preset.yml
└── README.md
本项目基于 howmp/dsh-pentest(MIT)增强。记录层(lib/pentest.js)、Web 视图(lib/ui-pentest*.js)、sqlite 后端(lib/storage-sqlite.js)、预设根(lib/preset-root.js)均 vendored 自原项目构建产物;本项目的增量是:
- 新增
lib/pentest-tools.js(v0.5 起瘦身为 4 个薄工具,执行下沉到 arsenal 容器),含范围门禁 / 知识懒加载 / 平台提交。 cordis.patch.yml不变地保留原四件事(sqlite 后端 /pentest→sqlite路由 / Web 视图 row / preset root)。preset/pentest/agent.cordis.yml在指挥官预设里追加pentest-toolsrow,并让执行子 agent 显式使用这些工具。
- 数据库:渗透记录写入
$DSH_HOME/storages/pentest-sessions.db(sqlite,经 bundle 补丁路由);宿主其它域不受影响。 - 授权:
authorization是审计事实、不是门禁——扫描/利用动作仍受部署沙箱与审批约束。若设置PENTEST_SCOPE,执行层会在工具级做范围门禁(白名单外目标被 block)。 - 记录按单会话作用域,无跨会话/项目续跑;重新开始一次 engagement 需新的
pentest_add_goal。 - 图布局为静态分层(可平移缩放,节点不可拖拽)。
MIT,见 LICENSE。记录层 / Web 视图 / sqlite 后端等 vendored 部分的版权归 howmp/dsh-pentest 原作者(MIT)。
同一份包同时支持这三代 dsh。0.1.7 动了三处会导致硬失败的地方,v1.6.0 起全部处理:
| 变更 | 症状 | 本插件的处理 |
|---|---|---|
agentPresets 改成声明式(register(definition)),目录式预设(<name>/agent.cordis.yml)被移除 |
「渗透」预设凭空消失 | lib/preset-root.js 双分支:新宿主走 register,plugins 里用 cordis:include 指回 composition(那份文件继续当唯一事实源);0.1.2 仍走 resolvedRoots 目录扫描;未知 API 显式抛错 |
dsh-workflow-worker-thread 被 dsh-workflow-ptc 取代(0.1.6-alpha.1 起) |
预设里每一行都报 never started(整份预设激活失败,不是降级) |
两份 composition 变体(agent.cordis.yml / agent.cordis.next.yml),按宿主能力选择;差异由测试锁死 |
插件安装门禁:peer 必须覆盖当前 dsh(includePrerelease 语义) |
installation rejected: Plugin … is incompatible |
peer 全部放宽为 caret(^0.1.0-rc.6 能覆盖 0.1.7-rc.2,精确版本不能) |
另有两处只有踩过才知道的细节:
cordis:include的path必须是 URL(传绝对路径字符串会 静默不加载,症状同上「每行 never started」);预设目录必须在 profile 的 node_modules 链上 (即作为包安装),否则解析不到 dsh 宿主包(@deepseek-ai/dsh-tool-*…),同样每行 never started。
dsh 0.1.5 的会话格式迁移(v0→v3)会拒绝旧版插件为驱动父会话投影而注入的合成
tool/call 事件,且迁移拒绝任何非已知 v0 类型的事件。本插件自 v1.4.0 起:
- 不再向父会话注入事件(删除
appendSubmissionProjection); - 「渗透」视图数据源改为只读路由
GET /api/pipadeep-pentest/graph?sessionId=…(直读 SQLite,形状与会话投影一致,跨 dsh 版本稳定,且含子 agent 提交的全部结果); - 因此 新会话在 0.1.2 / 0.1.5 上均可用。
旧会话(在 dsh ≤0.1.2 上用旧版插件创建、日志里含合成事件)迁移到 0.1.5 会报错, 可用修复脚本清除这些事件(会按打包 chunk 行的跨度正确重编号 seq):
node scripts/repair-v0-logs.mjs <session.jsonl.zstd | session.v4.jsonl.zstd> [more...]
node scripts/repair-v0-logs.mjs --all "$DSH_HOME/sessions" # 递归处理全部会话
node scripts/repair-v0-logs.mjs --dry-run <file> # 只报告- 默认先写
.bak备份;只删callId以pentest-submit-开头的合成tool/call。 - 需要
zstd可执行文件(macOS:brew install zstd)。 - 会话日志文件名随 dsh 版本演进:0.1.2 是
session.jsonl.zstd,0.1.7 是session.v4.jsonl.zstd(会话格式 v4);脚本对两者一视同仁。
每次探测到新资产或新漏洞时,插件会自动把当前资产拓扑导出成一份自包含的 交互式 HTML,并覆盖同一个文件(新增即刷新):
$DSH_HOME/storages/topology/<sessionId>.html
- 布局:横向树(目标 → 根域 → 子域 → IP/服务/应用/端点),按
parent边成层级; 容器原生滚动,几百个资产也看得清。 - 内容:节点显示类型 + value + meta,关联漏洞按严重度在节点上标色;点节点看详情 (子资产、关联漏洞、标识)。
- 交互:搜索过滤、类型图例开关、
▸/▾折叠子树、缩放、拖拽平移。离线可用(无 CDN)。 - 手动刷新 / 取路径:工具
pentest_topology。 - Web 查看:渗透视图标签栏的「拓扑图 ↗」,或直接访问
/api/pipadeep-pentest/topology?sessionId=<会话ID>。 - 输出目录可用环境变量
PENTEST_TOPOLOGY_DIR覆盖。
| 版本 | 内容 |
|---|---|
| v1.6.1 | 文档修正(安装命令、工具数、技能挂载方式、版本兼容章节) |
| v1.6.0 | 适配 dsh 0.1.7:预设声明式注册(双 API 兼容)、显式注册 5 个技能、workflow 双变体、peer 放宽为 caret(过安装门禁) |
| v1.5.0 | 资产拓扑图 HTML(探到新资产自动生成/更新)+ pentest_topology 工具 |
| v1.4.2 | 修复脚本随包分发(files 补 scripts/) |
| v1.4.1 | 旧日志修复脚本 repair-v0-logs.mjs(含 packed-chunk 跨度的 seq 重编号) |
| v1.4.0 | 适配 dsh 0.1.5:不再向父会话注入事件;「渗透」视图改由存储路由供图 |
| v1.3.4 | persona 配置双版本兼容(text / prefix) |
| v1.3.3 | 彻底零确认:用户即授权方,给出目标即开测 |