最近公司資安買了一套 SOC 產品。GCP Project 觸發 SCC 告警後,finding 會送到 Pub/Sub,再由 SOC 產品開事件單給專案團隊。
SCC 原始 finding 的內容其實很完整。我實際測試後,SOC 事件單卻只剩告警名稱。誰做的、什麼時間發生、哪個資源受到影響、從哪裡來,全部是 null。專案團隊收到單,還是得回到 GCP 從頭調查。這套 SOC 目前只幫忙開單。
我就想,如果 SCC 告警送出後,能讓 Agent 直接調查並產出報告,把誰、做了什麼、何時發生、從哪裡來、影響哪些資源整理好,團隊就能更快掌握範圍並開始止血。
參考 Google SecOps、Microsoft Sentinel、Microsoft Defender、AWS Security Hub 的事件調查欄位,以及公開的 SOC 調查報告,大概可以分成六個部分:
要產出這六個部分,得先確認 SCC finding 已經有哪些資料。
SCC finding 的 JSON 主要有三塊資料:
finding:告警名稱、category、severity、state、finding class、發生時間與建立時間。resource:受影響的 Project、VM、Service Account 或其他 GCP 資源。sourceProperties:偵測服務額外提供的欄位,每一種 finding 的內容都可能不同。Google 官方有一個 Persistence: GCE Admin Added SSH Key 範例。這個 finding 代表建立超過七天的 VM,其 instance metadata 裡的 ssh-keys 被修改。
官方 JSON 很長,以下只保留調查會用到的欄位:
{
"finding": {
"resourceName": "//compute.googleapis.com/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
"category": "Persistence: GCE Admin Added SSH Key",
"sourceProperties": {
"detectionCategory": {
"technique": "persistence",
"indicator": "audit_log",
"ruleName": "gce_admin",
"subRuleName": "instance_add_ssh_key"
},
"properties": {
"callerIp": "IP_ADDRESS",
"principalEmail": "PRINCIPAL_EMAIL",
"gceInstanceId": "COMPUTE_INSTANCE_ID",
"projectId": "PROJECT_ID",
"metadataKeyOperation": "ADDED",
"callerUserAgent": "USER_AGENT"
},
"evidence": [{
"sourceLogId": {
"timestamp": "TIMESTAMP",
"insertId": "INSERT_ID"
}
}]
}
}
}
只看這筆 finding,可以得到資料:
resourceName 指出哪一台 VM 受到影響。principalEmail 是執行操作的身分。callerIp 和 callerUserAgent 留下操作來源。metadataKeyOperation=ADDED 表示有人加入 SSH key。timestamp 和 insertId 可以回到 Cloud Audit Logs 找原始紀錄。對照前面的報告格式,這筆 finding 已經可以提供:
timestamp 與 insertId。雖然這些資訊已經可以放進報告,但我希望調查得更深入,再查詢以下資訊:
這些資訊要從 Cloud Audit Logs、Cloud Asset、IAM 與其他 GCP API 查詢,因此需要另外設計工具。
寫工具還有另一個原因。每次收到新的 finding,都要依照相同的調查項目,查詢這次事件的資源、操作紀錄與權限。只靠 Agent 當下決定查什麼,查詢順序、時間範圍與結果格式很容易不一致。
把查詢寫成工具後,可以固定每次要查的內容,並記錄查過哪些資料、使用什麼範圍,以及查不到的原因。這些結果再交給 Agent 整理成報告。
要詳細調查的資料分散在不同的 GCP 服務。依照調查時要回答的問題,分成六類:
| 類型 | 要回答的問題 | 資料來源 |
|---|---|---|
| 告警資料 | finding 發生在哪個資源,以及這筆告警提供哪些資料 | Security Command Center |
| 資源狀態 | 資源現在是否存在,目前有哪些設定與關聯資源 | Cloud Asset、各項資源 API |
| 身分與權限 | 操作者有哪些權限,權限何時被加入或移除 | IAM、Cloud Asset、Cloud Audit Logs |
| 操作紀錄 | 事件前後有哪些操作,由誰執行、從哪裡發出 | Cloud Audit Logs |
| 網路與資料存取 | 是否有網路連線、DNS 查詢、HTTP request 或資料存取 | VPC Flow Logs、Cloud DNS、Cloud Run logs、BigQuery Data Access logs |
| 查詢條件 | log 是否有開、目前權限能不能讀、查詢時間是否仍有資料 | 各項 log 設定與查詢結果 |
告警資料、資源狀態、身分權限與操作紀錄是每次調查都要查的項目。網路與資料存取則依 finding 類型決定,例如惡意網域需要查 DNS,BigQuery 異常需要查 Data Access logs。
分類完成後,將查詢拆成七個工具:
| 工具 | 負責查詢的內容 |
|---|---|
query_related_findings |
取得指定 finding 的完整內容 |
get_resource |
資源目前狀態、屬性與關聯資源 |
analyze_identity |
操作者或資源目前的 IAM 權限 |
query_control_plane |
Cloud Audit Logs 裡的操作紀錄與 IAM 異動 |
check_log_availability |
log 是否有開、是否能讀取、查詢時間是否有資料 |
query_network_activity |
VPC、DNS 與 Cloud Run request 活動 |
query_data_access |
BigQuery Data Access 紀錄 |
每個工具只處理一類查詢。Agent 從 finding 取得資源、操作者與時間,再用這些資料呼叫對應工具。工具會保留實際查詢範圍、結果是否完整,以及查不到資料的原因。
這樣每次調查都會查相同的項目,也能依 finding 類型增加需要的查詢。
告警通知裡已經有 finding,為什麼還要用 query_related_findings 再查一次?因為我希望之後可以重新執行同一筆告警的調查。報告會保留 finding 的完整名稱,需要重跑時,就能用這個名稱從 SCC 取得資料,再依照相同流程查詢資源、權限與操作紀錄,產出新的報告。
我把調查順序與報告要求寫進 Skill,讓 Agent 每次收到 finding,都依照相同的項目調查。
Agent 先用 query_related_findings 從 SCC 取得這筆 finding,確認受影響的資源,再用 get_resource 查資源目前的狀態與設定。事件時間則依 finding 中可用的時間資料決定。
事件前後的操作由 query_control_plane 查詢,包括誰執行了什麼、從哪裡發出,以及有哪些 IAM 權限異動。analyze_identity 則查操作者目前有哪些權限,報告中會分開說明目前的權限與事件前後的授權變化。
如果需要追查網路或資料存取,Agent 會先用 check_log_availability 確認 log 是否可用,再透過 query_network_activity 查網路活動,或用 query_data_access 查 BigQuery 的資料存取紀錄。
調查完成後,依照前面定義的格式整理報告。工具回報權限不足、log 未開啟或資料不完整時,也要把原因寫進待確認事項,避免把查不到寫成沒有發生。
工具與 Skill 設計完成後,預計由程式接收 Pub/Sub 訊息。SCC 發送 finding 後,程式會取得告警資訊並交給 Agent,讓它依照 Skill 的流程調查,最後產出報告。
SCC finding 已經提供不少事件資訊,再透過工具查詢資源、操作紀錄與權限,就能補上更深入的調查內容。Skill 則規定調查順序與報告格式,讓團隊收到報告時,可以直接查看事件經過與待確認的問題。
下一篇會實際觸發 SCC 告警,檢視 AI 產出的調查報告。
今天就先寫到這,我們明天見!