update SKILL

This commit is contained in:
rookit
2026-05-14 17:25:49 +08:00
parent adce862918
commit eb8d116e27
2 changed files with 65 additions and 48 deletions
@@ -29,7 +29,7 @@ Use this skill to guide the user through the full workflow — from requirement
- Before writing code, read `PLUGINS/SIRP/sirpcoremodel.py`; enum values must come only from the actual definitions in that file, never from memory or inference.
- All modules must inherit `BaseModule` and implement the `run()` method.
- SIRP data hierarchy: `Case → Alert → Artifact` (three-tier). Artifact is the smallest atomic investigation entity (an IP, a username); Alerts are attached to Cases; related alerts are aggregated into the same Case via `correlation_uid`. Enrichment is a cross-cutting attachment layer independent of the three-tier hierarchy — it can be attached to any level (Case / Alert / Artifact).
- Reference implementation: `MODULES/Cloud-01-AWS-IAM-Privilege-Escalation-via-AttachUserPolicy.py`.
- Reference implementation: `MODULES/Cloud-01-AWS-IAM-Privilege-Escalation-via-AttachUserPolicy.py`, which demonstrates the current recommended pattern for consuming raw_alerts, extracting Artifacts, assembling Alert/Case records, deduplicating appended alerts, and requesting case analysis scheduling.
- Data model reference: `PLUGINS/SIRP/sirpcoremodel.py`.
## Decision Flow
@@ -101,7 +101,7 @@ Before determining `correlation_uid`, first identify what kind of SOC scenario t
- User-reported phishing mail: prefer sender/sender domain. If the email title does not contain random values such as recipient names, timestamps, or order numbers, include a normalized title. Usually do not include recipient. Recommended window: `12h`, which keeps one phishing wave together without delaying notifications and response too much.
- Same malicious URL/domain delivery: use URL domain or normalized URL + sender domain. If the URL contains one-time tokens, use only the domain or stable path.
- Malicious process/command on endpoint: use host + stable process/command signature. If it looks like lateral movement or a hash-wide outbreak, aggregate by file hash/command signature and do not necessarily include host.
- Cloud IAM abnormal operation: usually use cloud account/tenant + principal identity + API/target resource. If investigating one broad attack wave, aggregate by principal identity or source IP and keep target resources as supporting context.
- Cloud IAM abnormal operation: usually use cloud account/tenant + principal identity + API/target resource. If investigating one broad attack wave, aggregate by principal identity or source IP and keep target resources as supporting context. For high-risk permission changes such as `AttachUserPolicy`, if a Case represents "the same principal granting high-risk permissions to the same target user", use `account_id + principal_user/principal_id + target_user`; do not include fields such as `policyArn`, `requestID`, or `eventID` when they would fragment one activity or add little aggregation value.
- C2 communication: use C2 IP/domain + internal host. If one C2 affects many hosts, aggregate by C2 first and keep affected hosts in the Case.
**Time-window guidance:**
@@ -180,28 +180,31 @@ class Module(BaseModule):
self.logger.info(f"Alert created: {saved_alert_row_id}")
# 7. Case management
try:
existing_case = Case.get_by_correlation_uid(correlation_uid, lazy_load=True)
if existing_case:
update_case = CaseModel(
alerts=[*existing_case.alerts, saved_alert_row_id],
row_id=existing_case.row_id
)
Case.update(update_case)
else:
new_case = CaseModel(
title=...,
severity=...,
impact=...,
priority=...,
confidence=Confidence.HIGH,
description=...,
correlation_uid=correlation_uid,
alerts=[saved_alert_row_id]
)
Case.create(new_case)
except Exception as e:
self.logger.error(f"Case operation failed: {str(e)}")
existing_case = Case.get_by_correlation_uid(correlation_uid, lazy_load=True)
if existing_case:
existing_case_row_id = existing_case.row_id
assert existing_case_row_id is not None
existing_alerts = existing_case.alerts or []
updated_alerts = existing_alerts if saved_alert_row_id in existing_alerts else [*existing_alerts, saved_alert_row_id]
update_case = CaseModel(
alerts=updated_alerts,
row_id=existing_case_row_id
)
Case.update(update_case)
Case.mark_analysis_requested(row_id=existing_case_row_id, cooldown_minutes=3)
else:
new_case = CaseModel(
title=...,
severity=...,
impact=...,
priority=...,
confidence=Confidence.HIGH,
description=...,
correlation_uid=correlation_uid,
alerts=[saved_alert_row_id]
)
created_case_row_id = Case.create(new_case)
Case.mark_analysis_requested(row_id=created_case_row_id, cooldown_minutes=3)
return True
```
@@ -215,7 +218,12 @@ Field mapping principles:
- AlertModel field population priority: ① map directly from the raw alert; ② derive via calculation or transformation from raw alert fields; ③ use a sensible default only when both previous steps fail.
- MITRE ATT&CK fields (`tactic`, `technique`, `sub_technique`) should be hardcoded based on the alert type.
- `Alert.create(alert_model)` automatically cascade-creates artifact records, writes the resulting row_id list back to `AlertModel.artifacts`, and then creates the alert record — attach artifacts to `alert_model`, do not call `Artifact.create` separately.
- Artifact selection principles: prefer stable, reusable, investigable entities; when deciding whether a field should become an Artifact, focus on whether it helps cross-alert correlation, investigation, evidence collection, or automated response.
- Avoid single-event random identifiers as Artifacts, such as request_id, event_id, trace_id, session_id, and uuid, unless the rule specifically investigates those IDs.
- Prefer preserving original, complete, stable entity values instead of only storing over-trimmed or overly generic derived values; derived values often fit better in Alert labels, descriptions, or unmapped data.
- ArtifactRole should describe the entity's relationship to the event: initiators are usually `ACTOR`, operated objects are usually `TARGET`, affected assets/environments are usually `AFFECTED`, and contextual entities are usually `RELATED` or `OTHER`.
- If fields in `unmapped` (or other high-value fields) need structured storage, create an `EnrichmentModel` record and attach it to the `enrichments` field of ArtifactModel / AlertModel / CaseModel.
- Use Enrichment only for supplementary information that is useful for investigation but does not fit core Alert/Case/Artifact fields. Do not convert every unmapped field into an Enrichment; keep it in `unmapped` by default and create Enrichment only when structured display or automation consumption is needed.
- For threat intelligence or Owner attribution on an entity, prefer storing directly in the corresponding `ArtifactModel` fields (`owner`, `reputation_score`, `reputation_provider`); create an EnrichmentModel and attach it to ArtifactModel only when richer structured content is needed.
### Step 6 — Add the Debug Entry Point
@@ -31,7 +31,7 @@ metadata:
- SIRP 数据层级:`Case → Alert → Artifact`(三级体系)。Artifact 是调查的最小原子实体(一个 IP、一个用户名),应尽量从 raw_alert
中提取;Alert 挂在 Case 下;同类告警通过 `correlation_uid` 聚合到同一个 Case。Enrichment 是独立于三级体系之外的横切附加层,可按需挂载到
Case / Alert / Artifact 任意一级。
- 参考实现:`MODULES/Cloud-01-AWS-IAM-Privilege-Escalation-via-AttachUserPolicy.py`
- 参考实现:`MODULES/Cloud-01-AWS-IAM-Privilege-Escalation-via-AttachUserPolicy.py`,体现当前推荐的 raw_alert 消费、Artifact 提取、Alert/Case 组装、Case 去重追加和分析调度调用方式
- 数据模型参考:`PLUGINS/SIRP/sirpcoremodel.py`
## 决策流程
@@ -113,7 +113,8 @@ metadata:
- 同一恶意 URL/域名投递:用 URL 域名或归一化 URL + 发件域;如果 URL 中包含一次性 token,应只取域名或稳定路径。
- 主机恶意进程/命令:用主机 + 进程名/命令行稳定特征;如果判断为横向传播或同一 hash 大范围爆发,可用文件 hash/命令特征,不一定加入主机。
- 云 IAM 异常操作:通常用云账号/租户 + 主体身份 + API/目标资源;如果关注一次大范围攻击,可按主体身份或源 IP
聚合,再用目标资源作为辅助信息。
聚合,再用目标资源作为辅助信息。例如 `AttachUserPolicy` 这类高危权限变更,如果 Case 表示"同一主体对同一目标用户的高危授权活动",可使用
`account_id + principal_user/principal_id + target_user`;不要加入 `policyArn``requestID``eventID` 这类会拆散同一活动或缺乏聚合价值的字段。
- C2 通信:用目标 C2 IP/域名 + 内部主机;如果同一 C2 影响多台主机,允许按 C2 先聚合,再在 Case 中保留受影响主机列表。
**时间窗口参考:**
@@ -194,28 +195,31 @@ class Module(BaseModule):
self.logger.info(f"Alert created: {saved_alert_row_id}")
# 7. Case 处理
try:
existing_case = Case.get_by_correlation_uid(correlation_uid, lazy_load=True)
if existing_case:
update_case = CaseModel(
alerts=[*existing_case.alerts, saved_alert_row_id],
row_id=existing_case.row_id
)
Case.update(update_case)
else:
new_case = CaseModel(
title=...,
severity=...,
impact=...,
priority=...,
confidence=Confidence.HIGH,
description=...,
correlation_uid=correlation_uid,
alerts=[saved_alert_row_id]
)
Case.create(new_case)
except Exception as e:
self.logger.error(f"Case operation failed: {str(e)}")
existing_case = Case.get_by_correlation_uid(correlation_uid, lazy_load=True)
if existing_case:
existing_case_row_id = existing_case.row_id
assert existing_case_row_id is not None
existing_alerts = existing_case.alerts or []
updated_alerts = existing_alerts if saved_alert_row_id in existing_alerts else [*existing_alerts, saved_alert_row_id]
update_case = CaseModel(
alerts=updated_alerts,
row_id=existing_case_row_id
)
Case.update(update_case)
Case.mark_analysis_requested(row_id=existing_case_row_id, cooldown_minutes=3)
else:
new_case = CaseModel(
title=...,
severity=...,
impact=...,
priority=...,
confidence=Confidence.HIGH,
description=...,
correlation_uid=correlation_uid,
alerts=[saved_alert_row_id]
)
created_case_row_id = Case.create(new_case)
Case.mark_analysis_requested(row_id=created_case_row_id, cooldown_minutes=3)
return True
```
@@ -232,8 +236,13 @@ class Module(BaseModule):
- MITRE ATT&CK 字段(`tactic``technique``sub_technique`)根据告警类型硬编码。
- `Alert.create(alert_model)` 会自动级联创建 artifacts 记录,并将生成的 row_id 列表回写到 AlertModel.artifacts,再创建
alert 记录——因此 artifacts 应挂载到 alert_model 上,不要单独调用 Artifact.create。
- Artifact 选择原则:优先选择稳定、可复用、可调查的实体;判断一个字段是否适合作为 Artifact 时,重点看它能否帮助跨告警关联、调查取证或自动化处置。
- 避免把单事件随机标识作为 Artifact,例如 request_id、event_id、trace_id、session_id、uuid 等;除非该 rule 的调查目标就是这些 ID。
- 优先保留原始、完整、稳定的实体值,避免只保存过度裁剪或泛化后的派生值;派生值更适合放在 Alert label、描述或 unmapped 中。
- ArtifactRole 应表达实体在事件中的关系:行为发起方通常为 `ACTOR`,被操作对象通常为 `TARGET`,受影响资产/环境通常为 `AFFECTED`,仅提供上下文的信息通常为 `RELATED``OTHER`
- 如果 unmapped 中有特殊价值的字段需要结构化存储,可创建 `EnrichmentModel` 记录并挂载到 ArtifactModel / AlertModel /
CaseModel 的 enrichments 字段。
- Enrichment 只用于补充对调查有帮助但不适合作为核心 Alert/Case/Artifact 字段的信息。不要把所有 unmapped 字段都转成 Enrichment;默认先放入 `unmapped`,只有需要结构化展示或后续自动化消费时再创建 Enrichment。
- 针对实体的威胁情报信息或 Owner 归属,优先直接存储到 `ArtifactModel` 的对应字段(如 `owner``reputation_score`
`reputation_provider`);若需要更丰富的结构化内容,再创建 EnrichmentModel 挂载到 ArtifactModel。