使用 Splunk SPL 建立偵測規則
概述
Splunk 搜尋處理語言 (SPL) 是 Splunk Enterprise Security 中用於建立關聯搜尋的主要查詢語言,能夠偵測可疑事件與模式。一個精心設計的偵測規則可以彙總、關聯並豐富安全事件,為 SOC 分析師產生可操作的 notable 事件。企業 SIEM 平均僅涵蓋 21% 的 MITRE ATT&CK 技術,因此熟練的 SPL 規則撰寫能力對於填補偵測缺口至關重要。
使用時機
- 在環境中部署或配置使用 Splunk SPL 建立偵測規則的功能時
- 建立符合合規要求的安全控制項時
- 為此領域建立或改進安全架構時
- 進行需要此實作的安全評估時
先決條件
- 已部署並配置 Splunk Enterprise Security (ES)
- 能夠存取 Splunk 搜尋與報告應用程式,並具備適當角色
- 了解通用資訊模型 (CIM) 資料模型
- 熟悉 MITRE ATT&CK 框架技術
- 了解組織的日誌來源與資料流程
核心 SPL 偵測規則模式
1. 閾值型偵測
偵測在時間視窗內超過定義計數的事件。
index=wineventlog sourcetype=WinEventLog:Security EventCode=4625
| stats count as failed_logins dc(TargetUserName) as unique_users by src_ip
| where failed_logins > 10 AND unique_users > 3
| eval severity="high"
| eval description="從 ".src_ip." 偵測到暴力破解攻擊,共 ".failed_logins." 次失敗登入,橫跨 ".unique_users." 個帳戶"
2. 序列型偵測(失敗登入後成功登入)
關聯一系列事件,指示成功的暴力破解攻擊。
index=wineventlog sourcetype=WinEventLog:Security (EventCode=4625 OR EventCode=4624)
| eval login_status=case(EventCode=4625, "failure", EventCode=4624, "success")
| stats count(eval(login_status="failure")) as failures count(eval(login_status="success")) as successes latest(_time) as last_event by src_ip, TargetUserName
| where failures > 5 AND successes > 0
| eval description="帳戶 ".TargetUserName." 從 ".src_ip." 經由暴力破解遭到入侵"
| eval urgency="critical"
3. 異常偵測搭配基線比較
將目前活動與基線期間進行比較,以偵測突發峰值。
index=proxy sourcetype=squid
| bin _time span=1h
| stats count as current_count by src_ip, _time
| join src_ip type=left [
search index=proxy sourcetype=squid earliest=-7d@d latest=-1d@d
| stats avg(count) as avg_count stdev(count) as stdev_count by src_ip
]
| eval threshold=avg_count + (3 * stdev_count)
| where current_count > threshold
| eval deviation=round((current_count - avg_count) / stdev_count, 2)
| eval description="從 ".src_ip." 的異常網頁流量 - 高於基線 ".deviation." 個標準差"
4. 橫向移動偵測
利用 Windows 登入事件識別潛在的橫向移動。
index=wineventlog sourcetype=WinEventLog:Security EventCode=4624 Logon_Type=3
| where NOT match(TargetUserName, ".*\\$")
| stats dc(dest) as unique_hosts values(dest) as hosts by src_ip, TargetUserName
| where unique_hosts > 5
| eval severity=case(unique_hosts > 20, "critical", unique_hosts > 10, "high", true(), "medium")
| eval description=TargetUserName." 從 ".src_ip." 透過網路登入存取了 ".unique_hosts." 台不重複主機"
5. 資料外洩偵測
監控大量出站資料傳輸。
index=firewall sourcetype=pan:traffic action=allowed direction=outbound
| stats sum(bytes_out) as total_bytes_out dc(dest_ip) as unique_destinations by src_ip, user
| eval total_mb=round(total_bytes_out/1048576, 2)
| where total_mb > 500 OR unique_destinations > 50
| lookup asset_lookup ip as src_ip OUTPUT asset_category, asset_owner
| eval severity=case(total_mb > 2000, "critical", total_mb > 1000, "high", true(), "medium")
| eval description=user." 傳送了 ".total_mb."MB 到 ".unique_destinations." 個不重複目的地"
6. PowerShell 可疑執行偵測
偵測經過編碼或混淆的 PowerShell 命令。
index=wineventlog sourcetype=WinEventLog:Security EventCode=4104
| where match(ScriptBlockText, "(?i)(encodedcommand|invoke-expression|iex|downloadstring|frombase64string|net\.webclient|invoke-webrequest|bitstransfer|invoke-mimikatz|invoke-shellcode)")
| eval decoded_length=len(ScriptBlockText)
| stats count values(ScriptBlockText) as commands by Computer, UserName
| where count > 0
| eval severity="high"
| eval mitre_technique="T1059.001"
| eval description="在 ".Computer." 上由 ".UserName." 執行可疑 PowerShell"
在 Splunk ES 中建立關聯搜尋
逐步流程
- 定義使用案例:對應至 MITRE ATT&CK 技術,並定義要偵測的行為
- 識別資料來源:確定哪些索引與 sourcetype 包含相關事件
- 撰寫基礎搜尋:建立提取相關事件的 SPL
- 加入彙總:使用
stats、eventstats或streamstats進行摘要 - 套用閾值:利用
where子句設定條件,區分正常與異常 - 豐富上下文:加入資產資訊、身分資料與威脅情資的查找
- 設定 Notable 事件:設定 severity、urgency 與 description 欄位
- 排程與測試:針對歷史資料執行並驗證偵測準確性
關聯搜尋配置範本
| tstats summariesonly=true count from datamodel=Authentication
where Authentication.action=failure
by Authentication.src, Authentication.user, _time span=5m
| rename "Authentication.*" as *
| stats count as total_failures dc(user) as unique_users values(user) as targeted_users by src
| where total_failures > 20 AND unique_users > 5
| lookup dnslookup clientip as src OUTPUT clienthost as src_dns
| lookup asset_lookup ip as src OUTPUT priority as asset_priority, category as asset_category
| eval urgency=case(asset_priority=="critical", "critical", asset_priority=="high", "high", true(), "medium")
| eval rule_name="針對多個帳戶的暴力破解"
| eval rule_description="從 ".src." 發生的多次驗證失敗,針對 ".unique_users." 個不重複帳戶"
| eval mitre_attack="T1110.001 - 密碼猜測"
上下文強化最佳實務
| lookup identity_lookup identity as user OUTPUT department, manager, risk_score as user_risk
| lookup asset_lookup ip as src_ip OUTPUT asset_name, asset_category, asset_priority, asset_owner
| lookup threatintel_lookup ip as src_ip OUTPUT threat_type, threat_confidence, threat_source
| eval context=case(
isnotnull(threat_type), "已知威脅: ".threat_type,
user_risk > 80, "高風險使用者: 風險評分 ".user_risk,
asset_priority=="critical", "重要資產: ".asset_name,
true(), "一般上下文"
)
效能最佳化
使用資料模型搭配 tstats
| tstats summariesonly=true count from datamodel=Network_Traffic
where All_Traffic.action=allowed
by All_Traffic.src_ip, All_Traffic.dest_ip, All_Traffic.dest_port, _time span=1h
| rename "All_Traffic.*" as *
限制時間範圍並使用索引欄位
index=wineventlog source="WinEventLog:Security" EventCode=4688
earliest=-15m latest=now()
| where NOT match(New_Process_Name, "(?i)(svchost|csrss|lsass|services)")
使用摘要索引建立歷史基線
| tstats count from datamodel=Authentication where Authentication.action=failure by Authentication.src, _time span=1h
| collect index=summary source="auth_failure_baseline" marker="report_name=auth_failure_hourly"
測試與驗證
針對已知攻擊模式進行測試
| makeresults count=1
| eval src_ip="10.0.0.50", failed_logins=25, unique_users=8, severity="high"
| eval description="測試暴力破解偵測"
| append [
search index=wineventlog sourcetype=WinEventLog:Security EventCode=4625
earliest=-24h latest=now()
| stats count as failed_logins dc(TargetUserName) as unique_users by src_ip
| where failed_logins > 10 AND unique_users > 3
| eval severity="high"
]
計算偵測指標
index=notable
| search rule_name="暴力破解*"
| stats count as total_alerts count(eval(status_label="Closed - True Positive")) as true_positives count(eval(status_label="Closed - False Positive")) as false_positives by rule_name
| eval precision=round(true_positives / (true_positives + false_positives) * 100, 2)
| eval fpr=round(false_positives / total_alerts * 100, 2)
MITRE ATT&CK 對映
| 技術 ID | 技術名稱 | SPL 偵測方法 |
|---|---|---|
| T1110.001 | 密碼猜測 | 針對 EventCode 4625 依 src_ip 設定閾值 |
| T1059.001 | PowerShell | 對 EventCode 4104 ScriptBlockText 進行模式比對 |
| T1021.002 | SMB/Windows 管理員共用 | 登入類型 3 搭配 dc(dest) 閾值 |
| T1048 | 經由 C2 的資料外洩 | 在時間視窗內彙總 bytes_out |
| T1053.005 | 排程工作 | EventCode 4698 搭配可疑命令模式 |
| T1003.001 | LSASS 記憶體 | 透過 Sysmon EventCode 10 對 lsass.exe 的處理程序存取 |