Splunk 偵測規則是 SIEM () 元件中的安全資訊與事件管理,與 Microsoft Sentinel 中的分析規則相比較。 本文說明如何識別、比較及遷移到 Microsoft Sentinel 的概念。 最好的方式是從 SIEM 遷移體驗開始,該體驗能即時識別 (OOTB) 分析規則,並自動轉換成。
如果你想遷移你的 Splunk Observability 部署,請進一步了解如何從 Splunk 遷移到 Azure Monitor 日誌。
稽核規則
Microsoft Sentinel 利用機器學習分析來創造高保真度且可執行的事件。 你現有的一些 Splunk 偵測在 Microsoft Sentinel 中可能已經重複,所以不要盲目遷移全部。 在確認現有偵測規則時,請檢視這些考量。
- 務必選擇適合規則遷移的使用案例,考量業務優先順序與效率。
- 請確認你了解 Microsoft Sentinel 的規則類型。
- 確認你是否理解 規則術語。
- 檢視過去6到12個月內沒有警示的過時規則,判斷它們是否仍然適用。
- 消除你經常忽略的低階威脅或警報。
- 確認連接的資料來源並檢視你的資料連接方式。 Microsoft Sentinel Analytics 要求該資料型別必須在 Log Analytics 工作空間中存在,才能啟用規則。 重新檢視資料收集的討論,確保你計畫偵測的應用案例中資料深度與廣度。 接著利用 SIEM 遷移經驗 ,確保資料來源被正確映射。
遷移規則
在你確定要遷移的 Splunk 偵測後,請檢視這些遷移過程中的考量:
- 比較 Microsoft Sentinel 現有的 OOTB 分析規則功能與您目前的使用案例。 利用 SIEM 遷移體驗 ,看看哪些 Splunk 偵測會自動轉換成 OOTB 範本。
- 將不符合 OOTB 分析規則的偵測轉換。 自動轉換 Splunk 偵測的最佳方式是使用 SIEM 遷移體驗。
- 透過探索社群資源,如 SOC Prime 威脅偵測市場,發掘更多適合您使用情境的演算法。
- 如果內建規則無法使用或無法自動翻譯,請手動翻譯偵測結果。 建立新的 KQL 查詢並檢視 規則映射。
欲了解更多資訊,請參閱 遷移偵測規則的最佳實務。
規則遷移步驟
確認你為每條想要遷移的規則都設置了測試系統。
準備一套為遷移規則的驗證流程,包括完整的測試情境和腳本。
確保你的團隊有可用的資源 來測試你遷移的規則。
確認你已連接所需的資料來源, 並檢視你的資料連接方式。
確認你的偵測是否以 Microsoft Sentinel 的 OOTB 範本形式提供:
利用 SIEM 遷移體驗 自動化翻譯與安裝 OOTB 範本。
欲了解更多資訊,請參閱 使用 SIEM 遷移體驗。
如果你的使用案例未反映在偵測中,請用 OOTB 規則範本為你自己的工作區建立規則。
在 Microsoft Sentinel 中,請前往內容中心。
篩選 內容類型 以取得 分析規則 範本。
尋找並 安裝/更新 每個對應的內容集線器解決方案或獨立分析規則範本。
欲了解更多資訊,請參閱「 開箱即用偵測威脅」。
如果你遇到 Microsoft Sentinel OOTB 規則未涵蓋的偵測,請先試用 SIEM 遷移體驗以實現自動轉換。
如果 OOTB 規則和 SIEM 遷移都無法完全轉換偵測,請手動建立規則。 在這種情況下,請依照以下步驟建立你的規則:
請確定你想在規則中使用的資料來源。 透過建立資料來源與資料表的對應表,來辨識你想查詢的 Microsoft Sentinel 資料表。
識別你想在規則中使用的資料中的任何屬性、欄位或實體。
明確你的規則標準和邏輯。 此階段,考慮尋找規則範本作為範例,以協助構建你的 KQL 查詢。
考慮篩選器、相關規則、活躍清單、參考集、監控清單、偵測異常、聚合等等。 你可以利用舊有 SIEM 提供的參考資料,了解如何 最佳地映射你的查詢語法。
先辨識觸發條件和規則動作,然後構建並檢視你的 KQL 查詢。 在檢視你的查詢時,請考慮 KQL 的優化指導資源。
針對你所有相關的使用情境來測試這個規則。 如果沒有達到預期結果,請檢視並編輯 KQL 並再次測試。
當你滿意時,就視為規則已遷移。 根據需要,為你的規則動作建立一套劇本。 欲了解更多資訊,請參閱 Microsoft Sentinel 中的「使用角色簿自動化威脅回應」。
了解更多關於分析規則的資訊:
- 建立自訂分析規則來偵測威脅。 使用 警報分組 來減少警報疲勞,方法是將在特定時間範圍內發生的警報分組。
- 將資料欄位映射到 Microsoft Sentinel 中的實體,讓 SOC 工程師能將實體定義為調查過程中追蹤的證據。 實體映射也讓 SOC 分析師能利用直覺式的調查圖 (invest-cases.md#use-the-investigation-graph-to-deep-deep) ,幫助節省時間與精力。
- 以 UEBA 資料調查事件,示範如何利用證據在事件預覽窗格中顯示事件、警示及與特定事件相關的書籤。
- Kusto 查詢語言 (KQL) ,你可以用它向你的 Log Analytics 資料庫發送唯讀請求,以處理資料並回傳結果。 KQL 也被用於其他 Microsoft 服務,例如 適用於端點的 Microsoft Defender 和 Application Insights。
比較規則術語
此表幫助你釐清基於 Microsoft Sentinel KQL) 規則Kusto 查詢語言 (與基於搜尋處理語言 (SPL) 的 Splunk 偵測的概念。
| Splunk | Microsoft Sentinel | |
|---|---|---|
| 規則類型 | • 排定 • 即時 |
• 排程查詢 • 融合 • Microsoft Security • 機器學習 (機器學習) 行為分析 |
| Criteria | 在 SPL 中定義 | 在 KQL 中定義 |
| 觸發條件 | • 結果數量 • 主持人數 • 資料來源數量 • 客製化 |
門檻:查詢結果數量 |
| 動作 | • 新增觸發警報 • 日誌事件 • 可查詢的輸出結果 • 以及更多 |
• 建立警報或事件 • 整合邏輯應用程式 |
繪製並比較規則範例
利用這些範例,在不同情境下比較並對應 Splunk 與 Microsoft Sentinel 的規則。
常見的搜尋指令
| SPL 指令 | 描述 | KQL 運算子 | KQL 範例 |
|---|---|---|---|
chart/ timechart |
回報會產生時間序列圖表的表格輸出。 | 渲染運算元 | … | render timechart |
dedup |
移除符合指定條件的後續結果。 | • 獨特 • 摘要 |
… | summarize by Computer, EventID |
eval |
計算一個表達式。 了解 常見 eval 指令。 |
延伸 | T | extend duration = endTime - startTime |
fields |
移除搜尋結果中的欄位。 | • 專案 • 專案外出 |
T | project cost=price*quantity, price |
head/tail |
回傳第一個或最後一個 N 個結果。 | 頂部 | T | top 5 by Name desc nulls last |
lookup |
從外部來源加欄位值。 | • 外部資料 • 查詢 |
KQL 範例 |
rename |
重新命名欄位。 使用萬用字元指定多個欄位。 | 專案更名 | T | project-rename new_column_name = column_name |
rex |
使用正則表達式指定群名稱以萃取欄位。 | 比賽正則表達式 | … | where field matches regex "^addr.*" |
search |
篩選結果至符合搜尋表達式的結果。 | 搜尋 | search "X" |
sort |
依指定欄位排序搜尋結果。 | 分類 | T | sort by strlen(country) asc, price desc |
stats |
提供統計資料,可依欄位分組。 了解更多 常見的統計指令。 | 總結 | KQL 範例 |
mstats |
類似統計,但用於指標而非事件。 | 總結 | KQL 範例 |
table |
指定結果集中應保留哪些欄位,並以表格格式保留資料。 | 專案 | T | project columnA, columnB |
top/rare |
顯示欄位的最常見或最不常見的值。 | 頂部 | T | top 5 by Name desc nulls last |
transaction |
群組搜尋結果,進而進入交易。 SPL 範例 |
範例: row_window_session | KQL 範例 |
eventstats |
它會從你活動中的欄位產生摘要統計,並將這些統計資料儲存在新欄位。 SPL 範例 |
範例: • 加入 • make_list • MV-擴展 |
KQL 範例 |
streamstats |
求出一個場的累積總和。 SPL 範例: ... | streamstats sum(bytes) as bytes _ total \| timechart |
row_cumsum | ...\| serialize cs=row_cumsum(bytes) |
anomalydetection |
找出指定欄位中的異常現象。 SPL 範例 |
series_decompose_anomalies () | KQL 範例 |
where |
使用 eval 表達式篩選搜尋結果。 以前比較過兩個不同的領域。 |
其中 | T | where fruit=="apple" |
lookup command: KQL 範例
Users
| where UserID in ((externaldata (UserID:string) [
@"https://storageaccount.blob.core.windows.net/storagecontainer/users.txt"
h@"?...SAS..." // Secret token to access the blob
])) | ...
stats command: KQL 範例
Sales
| summarize NumTransactions=count(),
Total=sum(UnitPrice * NumUnits) by Fruit,
StartOfMonth=startofmonth(SellDateTime)
mstats command: KQL 範例
T | summarize count() by price_range=bin(price, 10.0)
transaction command:SPL 範例
sourcetype=MyLogTable type=Event
| transaction ActivityId startswith="Start" endswith="Stop"
| Rename timestamp as StartTime
| Table City, ActivityId, StartTime, Duration
transaction command: KQL 範例
let Events = MyLogTable | where type=="Event";
Events
| where Name == "Start"
| project Name, City, ActivityId, StartTime=timestamp
| join (Events
| where Name == "Stop"
| project StopTime=timestamp, ActivityId)
on ActivityId
| project City, ActivityId, StartTime,
Duration = StopTime – StartTime
用於 row_window_session() 計算序列化列集中欄位的會話起始值。
...| extend SessionStarted = row_window_session(
Timestamp, 1h, 5m, ID != prev(ID))
eventstats command:SPL 範例
… | bin span=1m _time
|stats count AS count_i by _time, category
| eventstats sum(count_i) as count_total by _time
eventstats command: KQL 範例
這裡有一個例子,包含了這個 join 陳述:
let binSize = 1h;
let detail = SecurityEvent
| summarize detail_count = count() by EventID,
tbin = bin(TimeGenerated, binSize);
let summary = SecurityEvent
| summarize sum_count = count() by
tbin = bin(TimeGenerated, binSize);
detail
| join kind=leftouter (summary) on tbin
| project-away tbin1
這裡有一個例子,包含了這個 make_list 陳述:
let binSize = 1m;
SecurityEvent
| where TimeGenerated >= ago(24h)
| summarize TotalEvents = count() by EventID,
groupBin =bin(TimeGenerated, binSize)
|summarize make_list(EventID), make_list(TotalEvents),
sum(TotalEvents) by groupBin
| mvexpand list_EventID, list_TotalEvents
anomalydetection command:SPL 範例
sourcetype=nasdaq earliest=-10y
| anomalydetection Close _ Price
anomalydetection command: KQL 範例
let LookBackPeriod= 7d;
let disableAccountLogon=SignIn
| where ResultType == "50057"
| where ResultDescription has "account is disabled";
disableAccountLogon
| make-series Trend=count() default=0 on TimeGenerated
in range(startofday(ago(LookBackPeriod)), now(), 1d)
| extend (RSquare,Slope,Variance,RVariance,Interception,
LineFit)=series_fit_line(Trend)
| extend (anomalies,score) =
series_decompose_anomalies(Trend)
常用 eval 指令
| SPL 指令 | 描述 | SPL 範例 | KQL 指令 | KQL 範例 |
|---|---|---|---|---|
abs(X) |
回傳 X 的絕對值。 | abs(number) |
abs() |
abs(X) |
case(X,"Y",…) |
取 和 XY 參數對,其中 X 參數為布林表達式。 當將值值為 TRUE時,參數返回相應 Y 的參數。 |
SPL 範例 | case |
KQL 範例 |
ceil(X) |
數字上限X。 | ceil(1.9) |
ceiling() |
ceiling(1.9) |
cidrmatch("X",Y) |
識別屬於特定子網的 IP 位址。 | cidrmatch("123.132.32.0/25",ip) |
• ipv4_is_match()• ipv6_is_match () |
ipv4_is_match('192.168.1.1', '192.168.1.255')== false |
coalesce(X,…) |
回傳第一個不是空值的值。 | coalesce(null(), "Returned val", null()) |
coalesce() |
coalesce(tolong("not a number"),tolong("42"), 33) == 42 |
cos(X) |
計算 X 的餘弦。 | n=cos(0) |
因為 () | cos(X) |
exact(X) |
使用雙精度浮點運算來計算表達式 X。 | exact(3.14*num) |
todecimal() |
todecimal(3.14*2) |
exp(X) |
退貨 eX。 | exp(3) |
經驗 () | exp(3) |
if(X,Y,Z) |
若 X 評估為 TRUE,結果為第二個參數 Y。 若 X 評估為 FALSE,則結果 評估為第三個參數 Z。 |
if(error==200,"OK", "Error") |
iff() |
KQL 範例 |
isbool(X) |
如果X是布林值,則會回退TRUE。 |
isbool(field) |
• iff()• gettype |
iff(gettype(X) =="bool","TRUE","FALSE") |
isint(X) |
若為X整數,則回退TRUE。 |
isint(field) |
• iff()• gettype |
KQL 範例 |
isnull(X) |
若X為空,則回傳TRUE。 |
isnull(field) |
isnull() |
isnull(field) |
isstr(X) |
若為字串,X則回傳TRUE。 |
isstr(field) |
• iff()• gettype |
KQL 範例 |
len(X) |
此函數回傳字串 X的字元長度。 |
len(field) |
strlen() |
strlen(field) |
like(X,"y") |
回傳 TRUE 當且僅當 X 類似 的 SQLite 模式 Y。 |
like(field, "addr%") |
• has• contains• startswith• 配對正則表達 |
KQL 範例 |
log(X,Y) |
以第二個參數Y為基礎,回傳第一個參數X的日誌。 的 Y 預設值為 10。 |
log(number,2) |
• log• log2• log10 |
log(X)log2(X)log10(X) |
lower(X) |
回傳小寫值。X |
lower(username) |
托洛爾 | tolower(username) |
ltrim(X,Y) |
回傳 X 時參數中的 Y 字元從左側裁切。 預設輸出 Y 是空格和制表。 |
ltrim(" ZZZabcZZ ", " Z") |
trim_start() |
trim_start(“ ZZZabcZZ”,” ZZZ”) |
match(X,Y) |
若 X 符合正則表達式模式 Y,則回傳。 | match(field, "^\d{1,3}.\d$") |
matches regex |
… | where field matches regex @"^\d{1,3}.\d$") |
max(X,…) |
回傳欄位的最大值。 | max(delay, mydelay) |
• max()• arg_max() |
… | summarize max(field) |
md5(X) |
回傳字串值 X的 MD5 雜湊值。 |
md5(field) |
hash_md5 |
hash_md5("X") |
min(X,…) |
回傳欄位中的最小值。 | min(delay, mydelay) |
• min_of()• 最小 () • arg_min |
KQL 範例 |
mvcount(X) |
回傳該數值 (總) X 。 |
mvcount(multifield) |
dcount |
…| summarize dcount(X) by Y |
mvfilter(X) |
根據布林 X 表達式過濾多值欄位。 |
mvfilter(match(email, "net$")) |
mv-apply |
KQL 範例 |
mvindex(X,Y,Z) |
從起始位置 (零基) Y 回傳多值X參數的子集 (Z 可選) 。 |
mvindex( multifield, 2) |
array_slice |
array_slice(arr, 1, 2) |
mvjoin(X,Y) |
給定一個多值欄位X和字串分隔符Y,並使用 Y將各個X值連接起來。 |
mvjoin(address, ";") |
strcat_array |
KQL 範例 |
now() |
回傳目前時間,以 Unix 時間表示。 | now() |
now() |
now()now(-2d) |
null() |
不接受爭論,會退回 NULL。 |
null() |
無效 | null |
nullif(X,Y) |
包含兩個參數, X 且 Y,若參數不同則返回 X 。 否則,返回 NULL。 |
nullif(fieldA, fieldB) |
iff |
iff(fieldA==fieldB, null, fieldA) |
random() |
回傳一個介於 0 到 2147483647之間的偽隨機數。 |
random() |
rand() |
rand() |
relative_ time(X,Y) |
給定一個跨時期時間 X 與相對時間指定符 Y,回傳將的跨元時間值 Y 應用於 X。 |
relative_time(now(),"-1d@d") |
Unix 時間 | KQL 範例 |
replace(X,Y,Z) |
回傳一個由 將 替換 Z 成 字串中每個正則表達式字串 YX的字串。 |
退貨日期,月份和日期號碼互換。 例如,輸入的 4/30/2015 輸出為 30/4/2009:replace(date, "^(\d{1,2})/ (\d{1,2})/", "\2/\1/") |
replace() |
KQL 範例 |
round(X,Y) |
回退 X 後四捨五入至由 Y所指定的小數位數。 預設是四捨五入為整數。 |
round(3.5) |
round |
round(3.5) |
rtrim(X,Y) |
右側以 裁剪的字Y元返回X。 如果 Y 沒有指定,空格和制表符會被修剪。 |
rtrim(" ZZZZabcZZ ", " Z") |
trim_end() |
trim_end(@"[ Z]+",A) |
searchmatch(X) |
若事件與搜尋字串X相符,則回傳TRUE。 |
searchmatch("foo AND bar") |
如果 () | iff(field has "X","Yes","No") |
split(X,"Y") |
以多值欄位回傳 X ,並以分隔符 Y分割。 |
split(address, ";") |
split() |
split(address, ";") |
sqrt(X) |
回傳 的 X平方根。 |
sqrt(9) |
sqrt() |
sqrt(9) |
strftime(X,Y) |
回傳以 所Y指定格式所呈現的紀元時間值X。 |
strftime(_time, "%H:%M") |
format_datetime() |
format_datetime(time,'HH:mm') |
strptime(X,Y) |
給定一個由字串 X表示的時間,回傳從格式 Y中解析出來的值。 |
strptime(timeStr, "%H:%M") |
format_datetime () | KQL 範例 |
substr(X,Y,Z) |
回傳從起始位置 (一基底) Y 的子字串欄位X,涵蓋 Z (可選的) 字元。 |
substr("string", 1, 3) |
substring() |
substring("string", 0, 3) |
time() |
能以微秒級解析度回傳牆壁時鐘時間。 | time() |
format_datetime() |
KQL 範例 |
tonumber(X,Y) |
將輸入字串 X 轉換為數字, (Y 可選的預設值為) 10 定義要轉換的數字底邊。 |
tonumber("0A4",16) |
toint() |
toint("123") |
tostring(X,Y) |
描述 | SPL 範例 | tostring() |
tostring(123) |
typeof(X) |
回傳欄位類型的字串表示。 | typeof(12) |
gettype() |
gettype(12) |
urldecode(X) |
回傳已解碼的網址 X 。 |
SPL 範例 | url_decode |
KQL 範例 |
case(X,"Y",…) SPL 範例
case(error == 404, "Not found",
error == 500,"Internal Server Error",
error == 200, "OK")
case(X,"Y",…) KQL 範例
T
| extend Message = case(error == 404, "Not found",
error == 500,"Internal Server Error", "OK")
if(X,Y,Z) KQL 範例
iif(floor(Timestamp, 1d)==floor(now(), 1d),
"today", "anotherday")
isint(X) KQL 範例
iif(gettype(X) =="long","TRUE","FALSE")
isstr(X) KQL 範例
iif(gettype(X) =="string","TRUE","FALSE")
like(X,"y") 範例
… | where field has "addr"
… | where field contains "addr"
… | where field startswith "addr"
… | where field matches regex "^addr.*"
min(X,…) KQL 範例
min_of (expr_1, expr_2 ...)
…|summarize min(expr)
…| summarize arg_min(Price,*) by Product
mvfilter(X) KQL 範例
T | mv-apply Metric to typeof(real) on
(
top 2 by Metric desc
)
mvjoin(X,Y) KQL 範例
strcat_array(dynamic([1, 2, 3]), "->")
relative time(X,Y) KQL 範例
let toUnixTime = (dt:datetime)
{
(dt - datetime(1970-01-01))/1s
};
replace(X,Y,Z) KQL 範例
replace( @'^(\d{1,2})/(\d{1,2})/', @'\2/\1/',date)
strptime(X,Y) KQL 範例
format_datetime(datetime('2017-08-16 11:25:10'),
'HH:mm')
time() KQL 範例
format_datetime(datetime(2015-12-14 02:03:04),
'h:m:s')
tostring(X,Y)
回傳一個 X 欄位值,作為一個字串。
- 若 的
X值為數字,X則會被重新格式化為字串值。 - 若
X為布林值,X則被重新格式化為TRUE或FALSE。 - 若
X為數字,第二個參數Y可選,可 (hexX轉換為十六進位) 、commas(格式X(逗號加兩位小數點) ),或duration(將X時間格式轉換為可讀時間格式:HH:MM:SS) 。
tostring(X,Y) SPL 範例
此範例回傳:
foo=615 and foo2=00:10:15:
… | eval foo=615 | eval foo2 = tostring(
foo, "duration")
urldecode(X) SPL 範例
urldecode("http%3A%2F%2Fwww.splunk.com%2Fdownload%3Fr%3Dheader")
常見 stats 指令 KQL 範例
| SPL 指令 | 描述 | KQL 指令 | KQL 範例 |
|---|---|---|---|
avg(X) |
回傳域 X的值平均值。 |
平均 () | avg(X) |
count(X) |
返回場 X的出現次數 。 為了表示特定欄位值以匹配,格式化 X 為 eval(field="value")。 |
() | summarize count() |
dc(X) |
回傳場 X的不同值計數。 |
() 伯爵 | …\| summarize countries=dcount(country) by continent |
earliest(X) |
回傳時間上最早出現的 X值。 |
arg_min () | … \| summarize arg_min(TimeGenerated, *) by X |
latest(X) |
回傳時間順序上最新看到的 X值。 |
arg_max () | … \| summarize arg_max(TimeGenerated, *) by X |
max(X) |
返回欄位 X的最大值。 若 的 X 值非數字化,則透過字母順序找到最大值。 |
麥克斯 () | …\| summarize max(X) |
median(X) |
返回場中 X最中間的值。 |
百分位 () | …\| summarize percentile(X, 50) |
min(X) |
回傳欄位 X的最小值。 若 的 X 值非數字化,則透過字母順序找到最小值。 |
最小 () | …\| summarize min(X) |
mode(X) |
返回欄位 X的最常見值。 |
頂尖選手 () | …\| top-hitters 1 of Y by X |
perc(Y) |
返回欄位Y的百分位X數值。 例如,回 perc5(total) 傳欄位 total的第五百分位值。 |
百分位 () | …\| summarize percentile(Y, 5) |
range(X) |
返回場 X的最大值與最小值之間的差值。 |
射程 () | range(1, 3) |
stdev(X) |
回傳場 X的樣本標準差。 |
STDEV | stdev() |
stdevp(X) |
返回場 X的母體標準差。 |
STDEVP () | stdevp() |
sum(X) |
返回域 X的各值總和。 |
總 () | sum(X) |
sumsq(X) |
返回域 X的各值平方和。 |
||
values(X) |
會以多值條目回傳欄位中所有不同值 X 的清單。 數值的順序是按字母順序排列的。 |
make_set () | …\| summarize r = make_set(X) |
var(X) |
回傳場 X的樣本變異數。 |
變異數 | variance(X) |
後續步驟
在本文中,你學會了如何將遷移規則從 Splunk 映射到 Microsoft Sentinel。