前幾天做到 Day14、Day15 之後,BehaviorGuard 已經可以做 Alert Correlation。
Day14 做的是:
Same PID Correlation
Day15 又進一步做到:
Process Tree Correlation
也就是即使不同 PID,只要彼此有:
Parent
Child
Ancestor
Descendant
關係,就有機會被串成同一條 Attack Chain。
不過做到這裡其實還有一個問題:
我前面的 Correlation 測試,很多 Alert 都是自己在測試檔裡手動建立的。
例如:
alert1 = {
"rule": "BG-CMD-002",
"name": "Python Inline Code Execution",
"severity": "MEDIUM",
"pid": 7000
}
這種方式雖然可以驗證 Correlation Engine 的邏輯有沒有成功,但是它還不是完整的真實流程。
因為真正的 EDR 應該是:
真的 Process 發生
↓
Monitor 抓到
↓
Detection Engine 判斷
↓
產生 Alert
↓
送進 Correlation Engine
↓
判斷能不能形成 Attack Chain
所以 Day16 的目標很簡單:
前面的測試流程比較像:
test_process_tree_correlation.py
↓
手動建立 Alert
↓
add_alert()
↓
Correlation Engine
也就是:
「假設現在有 BG-CMD-002」
然後再測 Correlation Engine。
這樣可以測功能,但是不代表真正的 Monitor 已經接進去了。
真正要做到的是:
process_monitor.py
↓
真的抓到 python3 -c
↓
Detection Engine
↓
真的產生 BG-CMD-002
↓
送進 Correlation Engine
這才比較接近真正的 EDR Pipeline。
今天其實不是新增規則。
也不是新增新的 Alert。
而是在建立:
Pipeline
也就是資料從前面一路流到後面的流程。
目前想要的架構是:
Linux Process
↓
Process Monitor
↓
Detection Engine
↓
Detection Alert
↓
Correlation Engine
↓
Correlated Alert
這可以理解成一條生產線。
前面負責:
看發生了什麼
中間負責:
判斷有沒有可疑行為
後面負責:
判斷多個可疑行為是不是同一件事
這兩個概念我以前其實很容易混在一起。
Detection 比較像:
看到一個可疑行為。
例如:
python3 -c
命中:
BG-CMD-002
Python Inline Code Execution
這叫:
Detection Alert
但是 Correlation 是:
把多個 Alert 串起來看。
例如:
Python Inline Execution
↓
Network Activity
↓
External Connection
最後形成:
BG-CORR-005
CRITICAL
所以簡單來說:
Detection
=
抓單一事件
而:
Correlation
=
把多個事件串成故事
因為原本的 process_monitor.py 做到這裡就結束:
Process
↓
Detection Engine
↓
Alert
↓
print()
也就是只把 Alert 印在畫面上。
例如:
[ALERT] BG-CMD-002
Rule : Python Inline Code Execution
Severity : MEDIUM
印完之後,Correlation Engine 根本不知道這個 Alert 發生過。
所以今天就是在這裡多接一條:
Alert
↓
add_alert()
讓它變成:
Process
↓
Detection Engine
↓
Alert
↓
add_alert()
↓
Correlation Engine
今天在:
agent/process_monitor.py
裡加入:
from correlation.engine import add_alert
這個 function 是之前 Correlation Engine 已經寫好的。
它的用途就是:
把新的 Detection Alert
放進 Correlation Engine
所以原本 Detection 跟 Correlation 是:
分開的兩個模組
今天開始正式接在一起。
這也是今天一個很重要的地方。
目前 Detection Engine 的 Alert 格式大概是:
{
"rule_id": "...",
"rule_name": "...",
"severity": "...",
"description": "..."
}
但是 Correlation Engine 使用的是:
{
"rule": "...",
"name": "...",
"severity": "...",
"pid": ...
}
兩邊欄位名字不同。
例如:
Detection Engine:
rule_id
Correlation Engine:
rule
所以不能直接:
add_alert(alert)
不然 Correlation Engine 可能讀不到:
rule
這個欄位。
因此今天多做了一個動作:
中文可以理解成:
統一格式
例如 Detection Engine 給我們:
{
"rule_id": "BG-CMD-002",
"rule_name": "Python Inline Code Execution"
}
我們把它整理成:
{
"rule": "BG-CMD-002",
"name": "Python Inline Code Execution"
}
這樣 Correlation Engine 就看得懂。
今天加入的程式大概是:
normalized_alert = {
"rule": alert["rule_id"],
"name": alert["rule_name"],
"severity": alert["severity"],
"description": alert["description"],
"category": "Process/Command",
"pid": process["pid"],
"ppid": process["ppid"],
"process": process["name"],
"parent": parent_name,
"ancestors": ancestors,
"command": process["command"]
}
因為 Day15 已經做到:
Process Tree Correlation
所以 Correlation Engine 不只需要知道:
這是哪一條 Rule
還需要知道:
PID
PPID
Parent
Ancestors
例如:
PID : 2375578
PPID : 2375520
Process : python3
Parent : zsh
Ancestors : [2375520, 2375512, 2375506, 1]
這些資訊之後才能拿來判斷:
這個 Alert
和另外一個 Alert
是不是同一條 Process Tree
所以 Normalization 不只是改名字。
它同時也把:
Process Context
一起帶進 Correlation Engine。
整理完之後:
add_alert(normalized_alert)
這行就會把 Alert 送進:
correlation/engine.py
裡面的:
alert_buffer
可以把:
alert_buffer
想成 BehaviorGuard 的:
例如 30 秒內陸續發生:
BG-CMD-002
↓
BG-NET-005
↓
BG-NET-003
Correlation Engine 不能看到第一個 Alert 就忘記。
所以需要暫時保存:
最近發生過哪些 Alert
這就是:
alert_buffer = []
的用途。
Day14 我們已經設定:
TIME_WINDOW = 30
所以可以理解成:
BehaviorGuard 會保留最近一小段時間的 Alert,然後嘗試找出它們之間的關係。
修改完成後,先啟動:
PYTHONPATH=. python agent/process_monitor.py
BehaviorGuard 顯示:
========== BehaviorGuard ==========
[INFO] Continuous monitoring started.
[INFO] Press Ctrl+C to stop.
接著在另一個 Terminal 執行:
python3 -c 'import time; print("Day16"); time.sleep(5)'
這個 Command 裡使用:
python3 -c
所以會命中之前的:
BG-CMD-002
Python Inline Code Execution
BehaviorGuard 最後成功抓到:
[ALERT] BG-CMD-002
Rule : Python Inline Code Execution
Severity : MEDIUM
PID : 2375578
PPID : 2375520
Process : python3
Parent : zsh
Ancestors : [2375520, 2375512, 2375506, 1]
Command : python3 -c import time; print("Day16"); time.sleep(5)
Reason : Python executed code directly from the command line.
這代表第一件事情成功:
真實 Process
↓
真實 Detection
↓
BG-CMD-002
而因為程式裡已經加入:
add_alert(normalized_alert)
所以這個 Alert 同時也被送進:
Correlation Engine
這裡一開始我其實會疑惑:
既然已經送進 Correlation Engine
為什麼沒有 BG-CORR-002?
答案其實很簡單。
Correlation 本來就需要:
多個 Alert
現在只有:
BG-CMD-002
一個 Alert。
例如:
BG-CORR-002
需要的是:
BG-CMD-002
↓
BG-NET-003
但是今天還沒有把 Network Monitor 接進來。
所以目前只有:
BG-CMD-002
自然不會產生:
BG-CORR-002
這不是失敗。
反而代表:
Correlation Engine 沒有亂報 Alert。
今天真正成功的地方不是:
出現新的 BG-CORR
而是資料流程已經改變。
以前:
Process
↓
Detection
↓
印出 Alert
↓
結束
現在:
Process
↓
Detection
↓
BG-CMD-002
↓
Normalization
↓
add_alert()
↓
Correlation Engine
這就是 Day16 最主要的成果。
之後 BehaviorGuard 不會只有:
Process Alert
還會有:
Network Alert
File Alert
Persistence Alert
例如 Network 可能有:
Remote IP
Remote Port
Network Scope
File 可能有:
Path
SHA256
Mode
Persistence 可能有:
Cron
systemd
SSH Authorized Keys
Shell Profile
每一種資料都不同。
但是 Correlation Engine 還是需要一些共同欄位,例如:
rule
name
severity
category
pid
所以 Normalization 的作用就是:
不同來源
↓
統一格式
↓
Correlation Engine
Detection:
找到單一可疑事件
Correlation:
把多個事件串成 Attack Chain
兩者不是同一件事情。
以前我可能會覺得:
Detection Engine 有了
Correlation Engine 有了
那應該就完成了。
但今天才發現:
兩個模組就算都存在,如果沒有資料真的從前面流到後面,它們還是兩套分開的程式。
所以今天其實是在做:
Integration
也就是:
系統整合
一個 EDR 不只是:
很多 Rules
而是:
Telemetry
↓
Detection
↓
Alert
↓
Normalization
↓
Correlation
↓
Incident
↓
Response
今天 BehaviorGuard 開始從單純的:
Detection Script
慢慢變成:
Security Pipeline
不同模組如果使用不同欄位:
rule_id
rule
rule_name
name
後面會越來越難維護。
所以建立:
Normalized Alert
是一個很重要的設計。
今天只有:
BG-CMD-002
所以:
沒有 BG-CORR
是正常的。
因為 Correlation Rule 沒有完整成立。
這也代表 Correlation Engine 是:
有條件才觸發
而不是:
收到任何 Alert 就亂報。
| 功能 | 狀態 |
|---|---|
| 真實 Process Monitoring | ✅ |
| 真實 Command Detection | ✅ |
| BG-CMD-002 Detection | ✅ |
| Alert Normalization | ✅ |
| PID Context | ✅ |
| PPID Context | ✅ |
| Ancestor Context | ✅ |
| Detection → Correlation 串接 | ✅ |
| add_alert() 整合 | ✅ |
| Real Alert 進入 Correlation Buffer | ✅ |
| Network Correlation | 尚未 |
| File Correlation | 尚未 |
| Cross-Telemetry Correlation | 尚未完整 |
Day16 我沒有增加新的 Detection Rule。
今天真正做的是:
把原本分開的 Detection Engine
和 Correlation Engine
開始接在一起。
以前:
真實 Process
↓
Detection Alert
↓
只印在畫面上
現在:
真實 Process
↓
Detection Engine
↓
BG-CMD-002
↓
Normalized Alert
↓
add_alert()
↓
Correlation Engine
這次實際測試:
python3 -c 'import time; print("Day16"); time.sleep(5)'
成功被 BehaviorGuard 偵測成:
BG-CMD-002
Python Inline Code Execution
MEDIUM
並且帶有:
PID
PPID
Parent
Ancestors
Command
完整 Process Context。
雖然今天還沒有產生:
BG-CORR-xxx
但這是正常的。
因為目前只有 Command Alert 送進 Correlation Engine,Network Alert 還沒有接進來。
所以今天可以把 BehaviorGuard 的進度理解成:
Day14
手動 Alert
↓
Correlation
Day15
不同 PID
↓
Process Tree Correlation
Day16
真實 Detection
↓
Correlation Pipeline
今天最重要的收穫是:
Correlation Engine 不應該只靠測試資料,而是要真正接收前面 Detection 系統產生的 Alert。
BehaviorGuard 開始從:
「幾個分開的 Detection 功能」
慢慢變成:
「可以讓資料一路流動的 EDR Pipeline」
下一步才會繼續把:
Network Monitor
也接進同一個 Correlation Engine。
到那時候才有機會真正形成:
Command
↓
Network
↓
Correlated Alert
而不是再靠測試檔手動建立事件。