將 Splunk 偵測規則遷移至 Microsoft Sentinel
本文說明如何將 Splunk 偵測規則識別、比較和遷移至 Microsoft Sentinel 內建規則。
如果您想要移轉 Splunk 可檢視性部署,請深入瞭解如何 從 Splunk 移轉至 Azure 監視器記錄。
識別和移轉規則
Microsoft Sentinel 會使用機器學習分析來建立高逼真度且可採取動作的事件,而您的某些現有偵測在 Microsoft Sentinel 中可能是多餘的。 因此,請勿盲目移轉所有偵測和分析規則。 當您識別現有的偵測規則時,請檢閱這些考慮。
- 請務必選取使用案例來證明規則移轉的合理性,並考慮商務優先順序和效率。
- 請檢查您 瞭解 Microsoft Sentinel 規則類型。
- 請檢查您了解 規則術語。
- 檢閱過去 6-12 個月未觸發任何警示的任何規則,並判斷它們是否仍然相關。
- 排除您經常忽略的低階威脅或警示。
- 使用現有的功能,並檢查 Microsoft Sentinel 的 內建分析規則 是否可能解決您目前的使用案例。 因為 Microsoft Sentinel 會使用機器學習分析來產生高逼真度且可採取動作的事件,因此可能不再需要一些現有的偵測。
- 確認連線的數據源,並檢閱您的數據連線方法。 重新瀏覽資料收集交談,以確保您計劃偵測的使用案例的數據深度和廣度。
- 測試 SIEM 移轉體驗的功能,以判斷自動化翻譯是否合適。
- 探索社群資源, 例如 SOC Prime Threat Detection Marketplace ,以檢查您的規則是否可用。
- 請考慮在線查詢轉換器,例如 Uncoder.io 是否適用於您的規則。
- 如果規則無法使用或無法轉換,則必須使用 KQL 查詢手動建立規則。 檢閱 規則對應 以建立新的查詢。
深入瞭解 移轉偵測規則的最佳做法。
若要將分析規則遷移至 Microsoft Sentinel:
確認您已針對要移轉的每個規則,都已設定測試系統。
準備移轉規則的驗證程式 ,包括完整的測試案例和腳本。
請確定您的小組有實用的資源 來測試已移轉的規則。
確認您已連線任何必要的數據源, 並檢閱您的數據連線方法。
確認您的偵測是否可用為 Microsoft Sentinel 中的內建範本:
使用 SIEM 移轉體驗 將翻譯和移轉自動化。
如需詳細資訊,請參閱 使用 SIEM 移轉體驗。
如果內建規則已足夠,請使用內建規則範本來建立您自己的工作區規則。
在 Microsoft Sentinel 中,移至 [ 組態 > 分析 > 規則範本] 索引卷標,然後建立並更新每個相關的分析規則。
如需詳細資訊,請參閱 偵測現用的威脅。
如果您有 Microsoft Sentinel 內建規則未涵蓋的偵測,請嘗試在線查詢轉換器,例如 Uncoder.io 或 SPL2KQL ,將您的查詢轉換成 KQL。
識別觸發條件和規則動作,然後建構並檢閱您的 KQL 查詢。
如果內建規則和在線規則轉換器都不夠,您必須手動建立規則。 在這種情況下,請使用下列步驟開始建立規則:
識別您想要在規則中使用的數據來源。 您想要在 Microsoft Sentinel 中的數據源與數據表之間建立對應數據表,以識別您想要查詢的數據表。
識別您想要在規則中使用的數據中的任何屬性、欄位或實體 。
識別您的規則準則和邏輯。 在這個階段,您可能會想要使用規則範本作為如何建構 KQL 查詢的範例。
請考慮篩選、相互關聯規則、使用中清單、參考集、關注清單、偵測異常、匯總等等。 您可以使用舊版 SIEM 所提供的參考, 瞭解如何最好地對應查詢語法。
識別觸發條件和規則動作,然後建構並檢閱您的 KQL 查詢。 檢閱查詢時,請考慮 KQL 優化指引資源。
使用每個相關的使用案例測試規則。 如果它未提供預期的結果,您可能會想要檢閱 KQL 並再次進行測試。
當您滿意時,可以考慮移轉的規則。 視需要為您的規則動作建立劇本。 如需詳細資訊,請參閱 在 Microsoft Sentinel 中使用劇本將威脅回應自動化。
深入瞭解分析規則:
- 建立自定義分析規則來偵測威脅。 使用 警示群組 ,藉由將特定時間範圍內發生的警示分組,以減少警示疲勞。
- 將數據欄位對應至 Microsoft Sentinel 中的實體,讓 SOC 工程師能夠在調查期間將實體定義為要追蹤之證據的一部分。 實體對應也可讓 SOC 分析師利用直覺式 [調查圖表] (investigation-cases.md#use-the-investigation-graph-to-deep-dive)來協助減少時間和精力。
- 使用 UEBA 數據調查事件,例如如何使用辨識項來呈現事件、警示,以及事件預覽窗格中與特定事件相關聯的任何書籤。
- Kusto 查詢語言 (KQL),可用來將唯讀要求傳送至 Log Analytics 資料庫,以處理數據並傳回結果。 KQL 也會用於其他 Microsoft 服務,例如 適用於端點的 Microsoft Defender 和 Application Insights。
比較規則術語
此表格可協助您釐清 Microsoft Sentinel 中與 Splunk 相比的規則概念。
Splunk | Microsoft Sentinel | |
---|---|---|
規則類型 | •計劃 • 即時 |
• 排程查詢 •融合 • Microsoft 安全性 • 機器學習 (ML) 行為分析 |
準則 | 在SPL中定義 | 在 KQL 中定義 |
觸發條件 | • 結果數目 • 主機數目 • 來源數目 • 自定義 |
臨界值:查詢結果數目 |
動作 | • 新增至觸發的警示 • 記錄事件 • 輸出結果以查閱 • 等等 |
• 建立警示或事件 • 與 Logic Apps 整合 |
對應和比較規則範例
使用這些範例,在各種案例中比較和對應 Splunk 與 Microsoft Sentinel 的規則。
常見的搜尋命令
SPL 命令 | 描述 | KQL 運算子 | KQL 範例 |
---|---|---|---|
chart/ timechart |
傳回時間序列圖表的表格式輸出結果。 | render 運算符 | … | render timechart |
dedup |
拿掉符合指定準則的後續結果。 | • distinct • summarize |
… | summarize by Computer, EventID |
eval |
計算表達式。 瞭解 常見的評估命令。 | extend | T | extend duration = endTime - startTime |
fields |
從搜尋結果中移除欄位。 | • 專案 • project-away |
T | project cost=price*quantity, price |
head/tail |
傳回第一個或最後 N 個結果。 | top | T | top 5 by Name desc nulls last |
lookup |
從外部來源新增域值。 | • externaldata • 查閱 |
KQL 範例 |
rename |
重新命名字段。 使用通配符指定多個字段。 | project-rename | T | project-rename new_column_name = column_name |
rex |
指定使用正則表達式來擷取欄位的組名。 | 符合 regex | … | where field matches regex "^addr.*" |
search |
將結果篩選為符合搜尋表達式的結果。 | search | search "X" |
sort |
依指定的欄位排序搜尋結果。 | sort | T | sort by strlen(country) asc, price desc |
stats |
提供依欄位選擇性分組的統計數據。 深入瞭解 常見的統計數據命令。 | 總結 | KQL 範例 |
mstats |
類似於統計數據,用於計量而非事件。 | 總結 | KQL 範例 |
table |
指定要保留在結果集中的欄位,並以表格式格式保留數據。 | 專案 | T | project columnA, columnB |
top/rare |
顯示欄位最常見的值。 | top | T | top 5 by Name desc nulls last |
transaction |
將搜尋結果分組為交易。 SPL 範例 |
範例: row_window_session | KQL 範例 |
eventstats |
從事件中的欄位產生摘要統計數據,並將這些統計數據儲存在新欄位中。 SPL 範例 |
範例: • 聯結 • make_list • mv-expand |
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 表達式篩選搜尋結果。 用來比較兩個不同的欄位。 |
where | T | where fruit=="apple" |
lookup 命令: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 命令:KQL 範例
Sales
| summarize NumTransactions=count(),
Total=sum(UnitPrice * NumUnits) by Fruit,
StartOfMonth=startofmonth(SellDateTime)
mstats 命令:KQL 範例
T | summarize count() by price_range=bin(price, 10.0)
transaction 命令:SPL 範例
sourcetype=MyLogTable type=Event
| transaction ActivityId startswith="Start" endswith="Stop"
| Rename timestamp as StartTime
| Table City, ActivityId, StartTime, Duration
transaction 命令: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 命令:SPL 範例
… | bin span=1m _time
|stats count AS count_i by _time, category
| eventstats sum(count_i) as count_total by _time
eventstats 命令: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 命令:SPL 範例
sourcetype=nasdaq earliest=-10y
| anomalydetection Close _ Price
anomalydetection 命令: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)
常見的評估命令
SPL 命令 | 描述 | SPL 範例 | KQL 命令 | KQL 範例 |
---|---|---|---|---|
abs(X) |
傳回 X 的絕對值。 | abs(number) |
abs() | abs(X) |
case(X,"Y",…) |
接受 和 Y 自變數的X 配對,其中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,…) |
傳回非 Null 的第一個值。 | coalesce(null(), "Returned val", null()) |
coalesce() | coalesce(tolong("not a number"), tolong("42"), 33) == 42 |
cos(X) |
計算 X 的餘弦值。 | n=cos(0) |
cos() | cos(X) |
exact(X) |
使用雙精確度浮點算術評估表達式 X。 | exact(3.14*num) |
todecimal() | todecimal(3.14*2) |
exp(X) |
傳回 eX。 | exp(3) |
exp() | exp(3) |
if(X,Y,Z) |
如果 X 評估為 TRUE ,則結果會是第二個自變數 Y 。 如果 X 評估為 FALSE ,則結果會評估為第三個自變數 Z 。 |
if(error==200, "OK", "Error") |
iif() | KQL 範例 |
isbool(X) |
如果 X 為布林值,則傳TRUE 回 。 |
isbool(field) |
• iif() • gettype |
iif(gettype(X) =="bool","TRUE","FALSE") |
isint(X) |
如果 X 是整數,則傳TRUE 回 。 |
isint(field) |
• iif() • gettype |
KQL 範例 |
isnull(X) |
如果 X 為 null,則傳TRUE 回 。 |
isnull(field) |
isnull() | isnull(field) |
isstr(X) |
如果 X 為字串,則傳TRUE 回 。 |
isstr(field) |
• iif() • gettype |
KQL 範例 |
len(X) |
此函式會傳回字串 X 的字元長度。 |
len(field) |
strlen() | strlen(field) |
like(X,"y") |
只有在 與中的 Y SQLite 模式類似 時X ,才會傳TRUE 回 。 |
like(field, "addr%") |
• has • 包含 • startswith • 符合 regex |
KQL 範例 |
log(X,Y) |
使用第二個自變數做為基底,傳回第一個自變數X Y 的記錄。 Y 的預設值為 10 。 |
log(number,2) |
• 記錄 • log2 • log10 |
log(X) log2(X) log10(X) |
lower(X) |
傳回的 X 小寫值。 |
lower(username) |
tolower | tolower(username) |
ltrim(X,Y) |
會 X 傳回 參數 Y 中從左側修剪的字元。 的預設輸出 Y 是空格和索引標籤。 |
ltrim(" ZZZabcZZ ", " Z") |
trim_start() | trim_start(“ ZZZabcZZ”,” ZZZ”) |
match(X,Y) |
如果 X 符合 Regex 模式 Y,則傳回 。 | match(field, "^\d{1,3}.\d$") |
符合 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() • min() • 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 ,並使用聯結的個別值X Y 。 |
mvjoin(address, ";") |
strcat_array | KQL 範例 |
now() |
傳回以 Unix 時間表示的目前時間。 | now() |
now() | now() now(-2d) |
null() |
不接受自變數並傳 NULL 回 。 |
null() |
null | null |
nullif(X,Y) |
包含兩個自變數和 X Y ,如果自變數不同,則傳 X 回 。 否則傳回 NULL 。 |
nullif(fieldA, fieldB) |
iif | iif(fieldA==fieldB, null, fieldA) |
random() |
將之間的 0 虛擬隨機數傳回至 2147483647 。 |
random() |
rand() | rand() |
relative_ time(X,Y) |
指定 Epoch 時間和X 相對時間規範Y ,會傳回套用至 X 的 Y epoch 時間值。 |
relative_time(now(),"-1d@d") |
unix time | KQL 範例 |
replace(X,Y,Z) |
傳回字串,其Z 格式為字串X 中每次出現的正則表示式字串Y 。 |
傳回已切換月份和日數的日期。 例如,針對 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) |
傳 X 回的字元 Y 會從右側修剪。 如果未 Y 指定,則會修剪空格和索引標籤。 |
rtrim(" ZZZZabcZZ ", " Z") |
trim_end() | trim_end(@"[ Z]+",A) |
searchmatch(X) |
勾選事件符合搜尋字串 X ,則傳TRUE 回 。 |
searchmatch("foo AND bar") |
iif() | iif(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 的 epoch 時間值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 傳回 (選擇性) 字元的Z 子字串字段X 。 |
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) |
傳回已譯碼的 URL 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]), "->")
相對時間(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
是選擇性的,可以是hex
(轉換成X
十六進位)、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")
常見的統計數據命令 KQL 範例
SPL 命令 | 描述 | KQL 命令 | KQL 範例 |
---|---|---|---|
avg(X) |
傳回域 X 值的平均值。 |
avg() | avg(X) |
count(X) |
傳回欄位 X 的出現次數。 若要指出要比對的特定功能變數值,請將 格式 X 設定為 eval(field="value") 。 |
count() | summarize count() |
dc(X) |
傳回欄位 X 相異值的計數。 |
dcount() | …\| 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 是非數值,則會透過字母順序找到最大值。 |
max() | …\| summarize max(X) |
median(X) |
傳回欄位 X 的中間值。 |
percentile() | …\| summarize percentile(X, 50) |
min(X) |
傳回欄位 X 的最小值。 如果的值 X 是非數值,則會透過字母順序找到最小值。 |
min() | …\| summarize min(X) |
mode(X) |
傳回欄位 X 最頻繁的值。 |
top-hitters() | …\| top-hitters 1 of Y by X |
perc(Y) |
傳回欄位 Y 的百分位數X 值。 例如, perc5(total) 傳回欄位 total 的第五個百分位數值。 |
percentile() | …\| summarize percentile(Y, 5) |
range(X) |
傳回欄位 X 的最大值和最小值之間的差異。 |
range() | range(1, 3) |
stdev(X) |
傳回欄位 X 的範例標準偏差。 |
stdev | stdev() |
stdevp(X) |
傳回欄位 X 的母體標準偏差。 |
stdevp() | stdevp() |
sum(X) |
傳回欄位 X 的值總和。 |
sum() | sum(X) |
sumsq(X) |
傳回欄位 X 值的平方總和。 |
||
values(X) |
傳回欄位 X 的所有相異值清單做為多重值專案。 值的順序依字母順序排列。 |
make_set() | …\| summarize r = make_set(X) |
var(X) |
傳回欄位 X 的樣本變異數。 |
方差 | variance(X) |
下一步
在本文中,您已瞭解如何將移轉規則從Splunk對應至 Microsoft Sentinel。