mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-05-28 18:21:34 +02:00
141 lines
5.4 KiB
Go
141 lines
5.4 KiB
Go
package project
|
||
|
||
import (
|
||
"fmt"
|
||
"strings"
|
||
)
|
||
|
||
// 事实 category 常量(写入 upsert_project_fact 的 category 字段)。
|
||
const (
|
||
FactCategoryTarget = "target"
|
||
FactCategoryAuth = "auth"
|
||
FactCategoryInfra = "infra"
|
||
FactCategoryBusiness = "business"
|
||
FactCategoryFinding = "finding"
|
||
FactCategoryChain = "chain"
|
||
FactCategoryExploit = "exploit"
|
||
FactCategoryPOC = "poc"
|
||
FactCategoryNote = "note"
|
||
)
|
||
|
||
// RequiresAttackChainBody 判断该事实是否应携带可复现的攻击链 / exploit 详情(写在 body,非仅 summary)。
|
||
func RequiresAttackChainBody(category, factKey string) bool {
|
||
c := strings.ToLower(strings.TrimSpace(category))
|
||
switch c {
|
||
case FactCategoryFinding, FactCategoryChain, FactCategoryExploit, FactCategoryPOC, "vuln":
|
||
return true
|
||
}
|
||
key := strings.ToLower(strings.TrimSpace(factKey))
|
||
for _, prefix := range []string{"finding/", "chain/", "exploit/", "poc/"} {
|
||
if strings.HasPrefix(key, prefix) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// IsSparseFactBody 攻击链类事实 body 过短或缺少关键段落时返回 true(软校验,不阻断写入)。
|
||
func IsSparseFactBody(category, factKey, body string) bool {
|
||
if !RequiresAttackChainBody(category, factKey) {
|
||
return false
|
||
}
|
||
body = strings.TrimSpace(body)
|
||
if body == "" {
|
||
return true
|
||
}
|
||
lower := strings.ToLower(body)
|
||
// 至少应包含可复现线索:步骤/请求/命令/代码块 之一
|
||
hasSteps := strings.Contains(lower, "攻击链") || strings.Contains(lower, "## 攻击") ||
|
||
strings.Contains(lower, "## exploit") || strings.Contains(lower, "## poc")
|
||
hasHTTP := strings.Contains(lower, "```http") || strings.Contains(lower, "```bash") ||
|
||
strings.Contains(lower, "curl ") || strings.Contains(lower, "get ") || strings.Contains(lower, "post ")
|
||
hasReq := strings.Contains(lower, "请求") || strings.Contains(lower, "响应") || strings.Contains(lower, "payload")
|
||
// 无攻击链/POC/请求等结构线索,视为仅结论性描述(不论长短)
|
||
return !(hasSteps || hasHTTP || hasReq)
|
||
}
|
||
|
||
// FactBodyTemplate 按 category 返回建议的 body Markdown 骨架(供 Agent 填入真实内容)。
|
||
func FactBodyTemplate(category, factKey string) string {
|
||
if RequiresAttackChainBody(category, factKey) {
|
||
return attackChainFactBodyTemplate
|
||
}
|
||
return envFactBodyTemplate
|
||
}
|
||
|
||
const attackChainFactBodyTemplate = `## 结论(可验证,一句话)
|
||
<勿仅写「存在漏洞」;写明类型 + 位置 + 触发条件>
|
||
|
||
## 目标与入口
|
||
- 目标: <URL / IP:Port / 主机名>
|
||
- 入口: <路径 / 接口 / 参数>
|
||
- 前置条件: <匿名 / 角色 / Cookie / 其他依赖>
|
||
|
||
## 攻击链(逐步可复现)
|
||
1. <侦察/发现>
|
||
2. <利用/触发>
|
||
3. <影响证明(读文件、RCE 回显、越权数据等)>
|
||
|
||
## Exploit / POC
|
||
### 请求
|
||
` + "```http\n<METHOD> <path> HTTP/1.1\nHost: ...\n...\n\n<body>\n```" + `
|
||
|
||
### 响应 / 现象
|
||
<关键响应片段、状态码、差异点>
|
||
|
||
### 命令 / 脚本(如有)
|
||
` + "```bash\n<command>\n```" + `
|
||
|
||
## 关键证据
|
||
- <工具输出摘要 / 截图路径 / 会话或消息 ID>
|
||
|
||
## 关联
|
||
- related_vulnerability_id: <可选,对应 record_vulnerability 的 id>
|
||
- 依赖事实: <fact_key,如 auth/session_cookie>
|
||
|
||
## 备注与不确定性
|
||
<待验证假设、环境差异、绕过尝试记录>`
|
||
|
||
const envFactBodyTemplate = `## 摘要
|
||
<该事实的核心认知>
|
||
|
||
## 细节
|
||
<端口/版本/路径/凭据特征/业务规则等>
|
||
|
||
## 来源与证据
|
||
<命令输出、响应片段、发现时间>
|
||
|
||
## 关联
|
||
- 相关 fact_key: <可选>`
|
||
|
||
// FactRecordingGuidanceBlock 写入系统提示:要求事实沉淀攻击链上下文而非仅结论。
|
||
func FactRecordingGuidanceBlock() string {
|
||
return `### 事实写入规范(审计复现 / 知识沉淀)
|
||
|
||
- **summary**:索引用一行,须含「什么 + 在哪 + 如何触发/验证」要点,禁止只写结论(如仅写「存在 SQLi」)。
|
||
- **body**:完整可复现上下文,写入 ` + "`upsert_project_fact`" + ` 的 body 字段;索引不含 body,后续会话须靠 ` + "`get_project_fact`" + ` 取回。
|
||
- **category / fact_key 建议**:
|
||
- 环境认知:` + "`target/`" + `、` + "`auth/`" + `、` + "`infra/`" + `、` + "`business/`" + `(body 用环境模板即可)
|
||
- 发现与利用:` + "`finding/`" + `、` + "`chain/`" + `、` + "`exploit/`" + `、` + "`poc/`" + `(**必须**用攻击链模板填满 body:入口、逐步攻击链、原始请求/响应或命令、证据、关联漏洞 ID)
|
||
- **与漏洞记录分工**:` + "`record_vulnerability`" + ` 记可交付 findings;事实记**复现所需的全部上下文**(含失败尝试、绕过、依赖会话),二者可各记一次。
|
||
- 更新同一发现时保持相同 ` + "`fact_key`" + ` 覆盖写入,勿散落多个 key 导致上下文丢失。`
|
||
}
|
||
|
||
// SparseBodyWarning 攻击链类事实 body 不足时的工具返回提示(不阻断保存)。
|
||
func SparseBodyWarning(category, factKey string) string {
|
||
if !IsSparseFactBody(category, factKey, "") {
|
||
return ""
|
||
}
|
||
return fmt.Sprintf(
|
||
"\n\n⚠ 提示:category=%q / fact_key=%q 属于攻击链类事实,但 body 为空或过简。请补充完整攻击链与 POC(参考模板),便于后续审计复现。\n建议 body 骨架:\n%s",
|
||
category, factKey, FactBodyTemplate(category, factKey),
|
||
)
|
||
}
|
||
|
||
// SparseBodyWarningIfNeeded 根据实际 body 判断是否追加警告。
|
||
func SparseBodyWarningIfNeeded(category, factKey, body string) string {
|
||
if !IsSparseFactBody(category, factKey, body) {
|
||
return ""
|
||
}
|
||
return SparseBodyWarning(category, factKey)
|
||
}
|