| name | performing-ioc-enrichment-automation |
| description | 通过编排 VirusTotal、AbuseIPDB、Shodan、MISP 和其他情报源的查询, 自动化入侵指标(IOC)丰富化,提供上下文评分和处置建议。 适用于 SOC 分析师在告警分诊或事件调查期间需要对 IP、域名、URL 和文件哈希 进行快速多源丰富化时。
|
| domain | cybersecurity |
| subdomain | soc-operations |
| tags | ["soc","ioc","enrichment","automation","virustotal","abuseipdb","shodan","threat-intelligence"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
执行 IOC 丰富化自动化
适用场景
以下情况使用本技能:
- SOC 分析师在告警分诊期间需要快速从多个来源丰富化 IOC
- 高告警量需要自动化丰富化以减少手动查询时间
- 事件调查需要全面的 IOC 上下文进行范围评估
- SOAR 剧本需要将丰富化操作作为自动化分诊工作流的一部分
不适用于未经分析师审查的批量封锁决策——丰富化提供上下文,而非确定性的恶意/良性判断。
前置条件
- API 密钥:VirusTotal(免费或高级版)、AbuseIPDB、Shodan、URLScan.io、GreyNoise
- Python 3.8+ 含
requests、vt-py、shodan 库
- MISP 实例或 TIP(威胁情报平台)用于交叉参考组织情报
- SOAR 平台(可选)用于工作流集成
- 速率限制意识:VT 免费版(每分钟 4 次)、AbuseIPDB(每天 1000 次)、Shodan(每秒 1 次)
工作流程
步骤 1:构建统一丰富化引擎
创建多源丰富化管道:
import requests
import vt
import shodan
import time
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class EnrichmentResult:
ioc_value: str
ioc_type: str
virustotal: dict = field(default_factory=dict)
abuseipdb: dict = field(default_factory=dict)
shodan_data: dict = field(default_factory=dict)
greynoise: dict = field(default_factory=dict)
urlscan: dict = field(default_factory=dict)
misp_matches: list = field(default_factory=list)
risk_score: float = 0.0
disposition: str = "未知"
class IOCEnrichmentEngine:
def __init__(self, config):
self.vt_client = vt.Client(config["virustotal_key"])
self.shodan_api = shodan.Shodan(config["shodan_key"])
self.abuseipdb_key = config["abuseipdb_key"]
self.greynoise_key = config["greynoise_key"]
self.urlscan_key = config["urlscan_key"]
def ():
result = EnrichmentResult(ioc_value=ip_address, ioc_type=)
:
vt_obj = .vt_client.get_object()
result.virustotal = {
: vt_obj.last_analysis_stats.get(, ),
: vt_obj.last_analysis_stats.get(, ),
: (vt_obj.last_analysis_stats.values()),
: vt_obj.reputation,
: (vt_obj, , ),
: (vt_obj, , )
}
Exception e:
result.virustotal = {: (e)}
:
response = requests.get(
,
headers={: .abuseipdb_key, : },
params={: ip_address, : }
)
data = response.json()[]
result.abuseipdb = {
: data[],
: data[],
: data.get(, ),
: data.get(, ),
: data.get(, ),
: data.get(, )
}
Exception e:
result.abuseipdb = {: (e)}
:
host = .shodan_api.host(ip_address)
result.shodan_data = {
: host.get(, []),
: host.get(, ),
: host.get(, ),
: host.get(, ),
: host.get(, []),
: host.get(, )
}
shodan.APIError:
result.shodan_data = {: }
:
response = requests.get(
,
headers={: .greynoise_key}
)
gn_data = response.json()
result.greynoise = {
: gn_data.get(, ),
: gn_data.get(, ),
: gn_data.get(, ),
: gn_data.get(, )
}
Exception e:
result.greynoise = {: (e)}
result.risk_score = ._calculate_ip_risk(result)
result.disposition = ._determine_disposition(result.risk_score)
result
():
result = EnrichmentResult(ioc_value=domain, ioc_type=)
:
vt_obj = .vt_client.get_object()
result.virustotal = {
: vt_obj.last_analysis_stats.get(, ),
: vt_obj.last_analysis_stats.get(, ),
: vt_obj.reputation,
: (vt_obj, , ),
: (vt_obj, , ),
: (vt_obj, , {})
}
Exception e:
result.virustotal = {: (e)}
:
response = requests.get(
,
headers={: .urlscan_key}
)
scans = response.json().get(, [])
result.urlscan = {
: (scans),
: [s.get(, {}).get(, {}).get(, )
s scans[:]],
: scans[][][] scans
}
Exception e:
result.urlscan = {: (e)}
result.risk_score = ._calculate_domain_risk(result)
result.disposition = ._determine_disposition(result.risk_score)
result
():
result = EnrichmentResult(ioc_value=file_hash, ioc_type=)
:
vt_obj = .vt_client.get_object()
result.virustotal = {
: vt_obj.last_analysis_stats.get(, ),
: vt_obj.last_analysis_stats.get(, ),
: vt_obj.last_analysis_stats.get(, ),
: (vt_obj.last_analysis_stats.values()),
: (vt_obj, , ),
: (vt_obj, , {}).get(
,
),
: (vt_obj, , {}),
: (vt_obj, , )
}
vt.APIError:
result.virustotal = {: }
:
response = requests.post(
,
data={: , : file_hash}
)
mb_data = response.json()
mb_data[] == :
entry = mb_data[][]
result.abuseipdb = {
: entry.get(, ),
: entry.get(, []),
: entry.get(, ),
: entry.get(, ),
: entry.get(, )
}
Exception:
result.risk_score = ._calculate_hash_risk(result)
result.disposition = ._determine_disposition(result.risk_score)
result
():
score =
vt = result.virustotal
abuse = result.abuseipdb
gn = result.greynoise
(vt, ) vt:
score += (vt[] * , )
(abuse, ) abuse:
score += abuse[] *
(gn, ):
gn.get() == :
score +=
gn.get():
score -=
((score, ), )
():
score =
vt = result.virustotal
(vt, ) vt:
score += (vt[] * , )
vt.get(, ) < -:
score +=
((score, ), )
():
score =
vt = result.virustotal
(vt, ) vt:
total = vt.get(, )
detection_rate = vt[] / total total >
score = detection_rate *
((score, ), )
():
risk_score >= :
risk_score >= :
risk_score >= :
:
():
.vt_client.close()
步骤 2:事件调查的批量丰富化
iocs = [
{"type": "ip", "value": "185.234.218.50"},
{"type": "domain", "value": "evil-c2-server.com"},
{"type": "hash", "value": "a1b2c3d4e5f6..."},
{"type": "ip", "value": "45.33.32.156"},
]
config = {
"virustotal_key": "YOUR_VT_KEY",
"shodan_key": "YOUR_SHODAN_KEY",
"abuseipdb_key": "YOUR_ABUSEIPDB_KEY",
"greynoise_key": "YOUR_GREYNOISE_KEY",
"urlscan_key": "YOUR_URLSCAN_KEY"
}
engine = IOCEnrichmentEngine(config)
results = []
for ioc in iocs:
if ioc["type"] == "ip":
result = engine.enrich_ip(ioc["value"])
elif ioc["type"] == "domain":
result = engine.enrich_domain(ioc["value"])
elif ioc["type"] == "hash":
result = engine.enrich_hash(ioc["value"])
results.append(result)
time.sleep(15)
engine.close()
for r in results:
print(f"{r.ioc_type}: ")
()
()
()
步骤 3:与 Splunk 集成实现自动化丰富化
创建 Splunk 自定义搜索命令用于内联丰富化:
index=notable sourcetype="stash"
| table src_ip, dest_ip, file_hash, url
| lookup threat_intel_ip_lookup ip AS src_ip OUTPUT vt_score, abuse_score, disposition
| lookup threat_intel_hash_lookup hash AS file_hash OUTPUT vt_detections, malware_family
| eval combined_risk = coalesce(vt_score, 0) + coalesce(abuse_score, 0)
| where combined_risk > 50
| sort - combined_risk
步骤 4:生成丰富化报告
def generate_enrichment_report(results):
report = []
report.append("IOC 丰富化报告")
report.append("=" * 60)
for r in sorted(results, key=lambda x: x.risk_score, reverse=True):
report.append(f"\n{r.ioc_type.upper()}:{r.ioc_value}")
report.append(f" 风险评分:{r.risk_score}/100")
report.append(f" 处置:{r.disposition}")
if r.virustotal and "malicious" in r.virustotal:
report.append(f" VirusTotal:{r.virustotal['malicious']}/{r.virustotal.get('total_engines', 'N/A')} 恶意")
if r.abuseipdb and "confidence_score" in r.abuseipdb:
report.append(f" AbuseIPDB:{r.abuseipdb['confidence_score']}% 置信度,{r.abuseipdb['total_reports']} 条报告")
if r.greynoise and "classification" in r.greynoise:
report.append(f" GreyNoise:{r.greynoise['classification']}")
if r.shodan_data and "ports" in r.shodan_data:
report.append()
.join(report)
核心概念
| 术语 | 定义 |
|---|
| IOC 丰富化(IOC Enrichment) | 从多个外部来源向原始指标添加上下文情报的过程 |
| 综合风险评分(Composite Risk Score) | 结合多个情报来源的加权聚合评分,用于处置决策 |
| 速率限制(Rate Limiting) | API 请求限制,需要节流(VT 免费版:每分钟 4 次,AbuseIPDB:每天 1000 次) |
| GreyNoise RIOT | Rule It Out——GreyNoise 已知良性服务数据集,用于减少误报 |
| 被动 DNS(Passive DNS) | 显示域名到 IP 映射历史的 DNS 解析历史数据 |
| 去武装化(Defanging) | 修改 IOC 以在报告中安全处理(evil.com 变为 evil[.]com) |
工具与系统
- VirusTotal:多引擎恶意软件扫描器,提供文件、URL、IP 和域名分析,含 70+ 个 AV 引擎
- AbuseIPDB:社区 IP 信誉数据库,含滥用置信度评分和 ISP 归因
- Shodan:全网扫描器,提供 IP 地址的开放端口、Banner 和漏洞数据
- GreyNoise:互联网噪音情报,区分针对性攻击和机会性扫描
- URLScan.io:URL 分析平台,捕获截图、DOM 和网络请求用于钓鱼检测
常见场景
- 告警分诊丰富化:自动丰富化重大事件中的所有 IP,确定来源是否为已知恶意
- 事件范围评估:批量丰富化受损主机的所有 IOC,识别 C2 基础设施
- 威胁情报验证:丰富化收到的 IOC 信息流,在添加到封锁控制前验证质量
- 钓鱼 URL 分析:在用户通知前,使用 URLScan 和 VT 丰富化举报钓鱼邮件中的 URL
- 误报调查:丰富化被标记的 IP,确定其是否属于 CDN/云提供商(合法的)
输出格式
IOC 丰富化报告 — IR-2024-0450
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
丰富化时间:2024-03-15 14:30 UTC
处理 IOC 数:4
IP:185.234.218[.]50
风险评分: 87/100——恶意
VirusTotal:14/90 个引擎标记为恶意
AbuseIPDB: 92% 置信度,347 条报告
Shodan: 端口 [22, 80, 443, 4444],组织:防弹主机
GreyNoise: 恶意——已知 C2 基础设施
操作: 立即封锁
域名:evil-c2-server[.]com
风险评分: 73/100——恶意
VirusTotal:8/90 个引擎标记
URLScan: 5 次扫描,4 个恶意判定
WHOIS: 3 天前通过 Namecheap 注册
操作: 封锁并添加到 DNS 黑洞
哈希:a1b2c3d4e5f6...
风险评分: 91/100——恶意
VirusTotal:52/72 个引擎(Cobalt Strike Beacon)
MalwareBazaar:标签:cobalt-strike、beacon、c2
操作: 封锁哈希,隔离受影响终端
IP:45.33.32[.]156
风险评分: 5/100——干净
VirusTotal:0/90 个引擎
GreyNoise: 良性——Shodan 扫描器
操作: 无需操作(已知扫描器)