建立 ASIM 剖析器

已完成

進階安全性資訊模型 (ASIM) 剖析器使用者會在其查詢中使用整合剖析器 (而不是使用資料表名稱),來檢視正規化格式的資料,並在查詢中納入與結構描述相關的所有資料。 然後整合剖析器會使用來源專屬剖析器來處理每個來源的特定詳細資料。

Microsoft Sentinel 可為許多資料來源提供內建的來源專屬剖析器。 您可以在下列情況下修改或開發這些來源專屬剖析器:

您的裝置提供符合 ASIM 結構描述的事件,但裝置的來源特定剖析器和相關結構描述無法在 Microsoft Sentinel 中使用。

ASIM 來源專屬剖析器可供您的裝置使用,但您的裝置以不是 ASIM 剖析器預期的方式或格式傳送事件。 例如:

您的來源裝置可能設定為以非標準方式傳送事件。

您的裝置版本可能與 ASIM 剖析器所支援的版本不同。

中繼系統可能會收集、修改和轉送事件。

自訂剖析器開發流程

下列工作流程將描述開發自訂 ASIM 來源專屬剖析器的步驟總覽:

  1. 收集範例記錄。

  2. 識別傳送自來源的事件所代表的結構描述。

  3. 將來源事件欄位對應至已識別的結構描述。

  4. 為您的來源開發一個或多個 ASIM 剖析器。 您必須為每個與來源相關的結構描述開發篩選剖析器和無參數剖析器。

  5. 測試您的剖析器。

  6. 將剖析器部署到您的 Microsoft Sentinel 工作區。

  7. 更新相關的 ASIM 整合剖析器,以參考新的自訂剖析器。

  8. 您也可以將您的剖析器貢獻給主要 ASIM 散發版本。 貢獻的剖析器也可以在所有工作區中當作內建剖析器使用。

收集範例記錄

若要建置有效的 ASIM 剖析器,您需要一組代表性的記錄,在大部分情況下,這些記錄需要設定來源系統並將其連線至 Microsoft Sentinel。 如果您沒有可用的來源裝置,雲端隨用隨付服務可讓您部署許多裝置以供開發和測試。

此外,找出記錄的廠商文件和範本來確認廣泛的記錄格式涵蓋範圍,將有助於加速開發和減少錯誤。

一組代表性的記錄應該包括:

  • 事件結果不同的事件。
  • 回應動作不同的事件。
  • 格式不同的使用者名稱、主機名稱和識別碼,以及其他格式不同且需要值正規化的欄位。

對應

開發剖析器之前,請先將來源事件中可用的資訊對應至您識別的結構描述:

  • 對應所有必要欄位,最好也包括建議欄位。
  • 嘗試將來源中可用的任何資訊對應至正規化欄位。 如果不是所選結構描述的一部分,請考慮對應至其他結構描述中可用的欄位。
  • 將來源欄位的值對應至 ASIM 所允許的正規化值。 原始值會儲存在不同的欄位中,例如 EventOriginalResultDetails。

開發剖析器

針對每個相關結構描述開發篩選剖析器和無參數剖析器。

自訂剖析器是 Microsoft Sentinel 記錄頁面中開發的 KQL 查詢。 剖析器查詢有三個部分:

篩選 > 剖析 > 準備欄位

篩選相關的記錄

在許多情況下,Microsoft Sentinel 中的資料表會包含多種事件類型。 例如:

  • Syslog 資料表具有來自多個來源的資料。
  • 自訂資料表可能包含來自單一來源的資訊,但該來源提供一個以上的事件類型,而且可符合各種結構描述。

因此,剖析器應該先只篩選與目標結構描述相關的記錄。

KQL 中的篩選會使用 where 運算子來完成。 例如,Sysmon 事件 1 會報告流程建立,因此會正規化為 ProcessEvent 結構描述。 Sysmon 事件 1 事件是 Event 資料表的一部分,因此您會使用下列篩選條件:

Event | where Source == "Microsoft-Windows-Sysmon" and EventID == 1

重要

剖析器不應依時間進行篩選。 使用剖析器的查詢會套用時間範圍。

使用「關注清單」來依據來源類型篩選

在某些情況下,事件本身不包含允許篩選特定來源類型的資訊。

例如,Infoblox DNS 事件會以 Syslog 訊息的形式傳送,而且很難區別其與傳送自其他來源的 Syslog 訊息有何不同。 在這種情況下,剖析器會依賴定義相關事件的來源清單。 此清單會在 ASimSourceType 關注清單中維護。

若要在您的剖析器中使用 ASimSourceType 關注清單:

  • 在剖析器開頭包含下列這一行:
let Sources_by_SourceType=(sourcetype:string){_GetWatchlist('ASimSourceType') | where SearchKey == tostring(sourcetype) | extend Source=column_ifexists('Source','') | where isnotempty(Source)| distinct Source };
  • 在剖析器篩選區段中新增使用關注清單的篩選條件。 例如,Infoblox DNS 剖析器會在篩選區段中包含下列內容:
| where Computer in (Sources_by_SourceType('InfobloxNIOS'))

若要在剖析器中使用此範例:

  • 將 Computer 取代為欄位的名稱,該欄位應包含來源的來源資訊。 針對以 Syslog 為基礎的任何剖析器,您可以將此欄位保留為 Computer。

  • 將 InfobloxNIOS 權杖取代為您為剖析器選擇的值。 通知剖析器使用者,他們必須使用您選取的值來更新 ASimSourceType 關注清單,以及傳送此類型事件的來源清單。

根據剖析器參數進行篩選

開發篩選剖析器時,請確認您的剖析器可接受相關結構描述的篩選參數,如該結構描述的參考文章所述。 使用現有的剖析器作為起點,可確保剖析器包含正確的函式簽章。 在大部分情況下,實際篩選程式碼也會類似於相同結構描述的篩選剖析器。

篩選時,請確定您:

  • 先篩選,然後再使用實體欄位進行剖析。 如果篩選的結果不夠精確,請在剖析之後重複測試,以微調您的結果。 如需詳細資訊,請參閱篩選最佳化。
  • 如果未定義參數,且仍有預設值,請不要篩選。

下列範例示範如何實作字串參數的篩選,其中預設值通常是 '*',而清單參數的預設值通常是空的清單。

srcipaddr=='*' or ClientIP==srcipaddr
array_length(domain_has_any) == 0 or Name has_any (domain_has_any)

篩選最佳化

若要確保剖析器的效能,請注意下列篩選建議:

  • 一律篩選內建欄位,而不是剖析的欄位。 雖然使用剖析的欄位進行篩選,有時候更輕鬆,但會大幅影響效能。
  • 使用提供最佳化效能的運算子。 尤其是 ==、has 和 startswith。 使用 contains 或 matches 規則運算式也會大幅影響效能。

提高效能的篩選建議並非都很容易遵循。 例如,使用 has 的準確度比使用 contains 低。 在其他情況下,比對內建欄位 (例如 SyslogMessage) 比起比較擷取的欄位 (例如 DvcAction) 更不精確。 在這種情況下,建議您仍在內建欄位上使用效能最佳化運算子進行預先篩選,並在剖析之後使用更精確的條件重複進行篩選。

如需範例,請參閱下列 Infoblox DNS 剖析器程式碼片段。 剖析器首先會檢查 SyslogMessage 欄位是否有 client 一詞。 不過,字詞可能會用於訊息的不同位置,因此在剖析 Log_Type 欄位之後,剖析器會再次檢查 client 一詞是否確實是欄位的值。

Syslog | where ProcessName == "named" and SyslogMessage has "client"
…
      | extend Log_Type = tostring(Parser[1]),
      | where Log_Type == "client"

剖析

查詢選取相關記錄之後,可能需要對其進行剖析。 一般而言,如果單一文字欄位中傳達多個事件欄位,就會需要剖析。

執行剖析的 KQL 運算子如下所列 (依效能最佳化排序)。 第一個是效能最佳化程度最高的項目,而最後一個則是效能最佳化程度最低的項目。

運算子 描述
split 剖析分隔的值字串。
parse_csv 剖析格式化為 CSV (逗號分隔值) 行的值字串。
parse (剖析) 使用模式剖析任一字串中的多個值,模式這可以是具有較佳效能的簡化模式,或是規則運算式。
extract_all 使用規則運算式剖析任一字串中的單一值。 extract_all 具有與parse 類似的效能 (如果後者使用規則運算式)。
extract (擷取) 使用規則運算式從任一字串中擷取單一值。 如果需要單一值,使用 extract 可提供比 parse 或 extract_all 更好的效能。 不過,對相同來源字串啟用多個 extract 比單一 parse 或 extract_all 效率更低,因此應該避免。
parse_json 在格式化為 JSON 的字串中剖析值。 如果只需要 JSON 中的幾個值,使用 parse、extract 或 extract_all 可提供較好的效能。
parse_xml 在格式化為 XML 的字串中剖析值。 如果只需要 XML 中的幾個值,使用 parse、extract 或 extract_all 可提供較好的效能。

除了剖析字串之外,剖析階段可能需要對原始值進行更多處理,包括:

  • 調整格式和類型轉換。 擷取來源欄位後,可能需要加以格式化以符合目標結構描述欄位。 例如,您可能需要將代表日期和時間的字串轉換成日期時間欄位。 在這些情況下,todatetime 和 tohex 等函式就能幫上忙。

  • 值查閱。 擷取來源欄位的值後,可能需要將值對應至專為目標結構描述欄位指定的值集合。 例如,某些來源會報告數值型的 DNS 回應碼,但結構描述要求使用更常見的文字回應碼。 iff 和 case 函式有助於對應一些值。

    例如,Microsoft DNS 剖析器會使用 iff 陳述式,根據事件識別碼和回應碼指派 EventResult 欄位,如下所示:

    extend EventResult = iff(EventId==257 and ResponseCode==0 ,'Success','Failure')
    

    若是數個值,請使用 datatable 和 lookup,如相同的 DNS 剖析器中所示範:

    let RCodeTable = datatable(ResponseCode:int,ResponseCodeName:string) [ 0, 'NOERROR', 1, 'FORMERR'....];
    ...
     | lookup RCodeTable on ResponseCode
     | extend EventResultDetails = case (
     isnotempty(ResponseCodeName), ResponseCodeName,
     ResponseCode between (3841 .. 4095), 'Reserved for Private Use',
     'Unassigned')
    

對應值

在許多情況下,必須將擷取的原始值正規化。 例如,在 ASIM 中,MAC 位址會使用冒號做為分隔符號,而來源可能會傳送以連字號分隔的 MAC 位址。 用於轉換值的主要運算子是 extend,以及一組廣泛的 KQL 字串、數值和日期函式,如上述剖析一節中所示。

當需要將一組值對應至目標欄位所允許的值時,請使用 case、iff 和 lookup 陳述式。

當每個來源值都對應至目標值時,請使用 datatable 運算子定義對應並查閱對應。 例如:

let NetworkProtocolLookup = datatable(Proto:real, NetworkProtocol:string)[
        6, 'TCP',
        17, 'UDP'
   ];
    let DnsResponseCodeLookup=datatable(DnsResponseCode:int,DnsResponseCodeName:string)[
      0,'NOERROR',
      1,'FORMERR',
      2,'SERVFAIL',
      3,'NXDOMAIN',
      ...
   ];
   ...
   | lookup DnsResponseCodeLookup on DnsResponseCode
   | lookup NetworkProtocolLookup on Proto

請注意,當對應只有兩個可能的值時,lookup 也很實用且有效率。

當對應條件比較複雜時,請使用 iffcase 函式。 iff 函式會啟用兩個值的對應:

| extend EventResult = 
      iff(EventId==257 and ResponseCode==0,'Success','Failure’)

case 函式可支援兩個以上的目標值。 下列範例示範如何合併 lookupcase。 如果找不到查閱值,上述 lookup 範例會在 DnsResponseCodeName 欄位中傳回空白值。 下列 case 範例會使用 lookup 作業的結果加強 (如適用),並指定其他條件。

| extend DnsResponseCodeName = 
      case (
        DnsResponseCodeName != "", DnsResponseCodeName,
        DnsResponseCode between (3841 .. 4095), 'Reserved for Private Use',
        'Unassigned'
      )

準備結果集中的欄位

剖析器必須準備結果集中的欄位,以確保使用正規化欄位。

下列 KQL 運算子可用來準備結果集中的欄位:

運算子 描述 在剖析器中的使用時機
project-rename 重新命名欄位。 如果有一個欄位存在於實際事件中,而且只需要將其重新命名,請使用 project-rename。 重新命名的欄位仍會像內建欄位一樣運作,而欄位上的作業會有更好的效能。
project-away 移除欄位。 針對您想要從結果集中移除的特定欄位,使用 project-away。 建議不要從結果集中移除未正規化的原始欄位,除非它們會造成混淆或非常大型,而且可能會影響效能。
專案 選取之前已存在或建立為陳述式一部分的欄位,並移除所有其他欄位。 不建議在剖析器中使用,因為剖析器不應該移除任何其他未正規化的欄位。 如果您需要移除特定欄位,例如剖析期間所使用的暫存值,請使用 project-away 從結果中移除這些欄位。
extend 新增別名。 除了在產生導出欄位中具有重要角色之外,extend 運算子也會用來建立別名。

處理剖析變體

在許多情況下,事件串流中的事件會包含需要不同剖析邏輯的變體。 若要剖析單一剖析器中的不同變體,請使用條件陳述式 (例如 iff 和 case) 或使用聯合結構。

若要使用 union 來處理多個變體,請為每個變體建立個別函式,並使用聯合陳述式合併結果:

let AzureFirewallNetworkRuleLogs = AzureDiagnostics
    | where Category == "AzureFirewallNetworkRule"
    | where isnotempty(msg_s);
let parseLogs = AzureFirewallNetworkRuleLogs
    | where msg_s has_any("TCP", "UDP")
    | parse-where
        msg_s with           networkProtocol:string 
        " request from "     srcIpAddr:string
        ":"                  srcPortNumber:int
    …
    | project-away msg_s;
let parseLogsWithUrls = AzureFirewallNetworkRuleLogs
    | where msg_s has_all ("Url:","ThreatIntel:")
    | parse-where
        msg_s with           networkProtocol:string 
        " request from "     srcIpAddr:string
        " to "               dstIpAddr:string
    …
union parseLogs,  parseLogsWithUrls…

為避免重複事件和過度處理,請確保每個函式會先使用原生欄位篩選所要剖析的事件。 此外,如有需要,請在使用 union 之前,對每個分支使用 project-away。

部署剖析器

您可以將剖析器複製到 Azure 監視器記錄頁面,並將查詢儲存為函式,藉此來手動部署剖析器。 這個方法在測試時很有用。 如需詳細資訊,請參閱<建立函式>。

若要部署大量剖析器,我們建議使用剖析器的 ARM 範本,如下所示:

  1. 根據每個結構描述的相關範本建立 YAML 檔案,並在其中納入您的查詢。 從與結構描述和剖析器類型相關的 YAML 範本開始,篩選或無參數。

  2. 使用從 ASIM Yaml 到 ARM 範本的轉換器,將 YAML 檔案轉換成 ARM 範本。

  3. 如果部署一項更新,請使用入口網站或函式刪除 PowerShell 工具來刪除舊版的函式。

  4. 使用 Azure 入口網站或 PowerShell 部署範本。

您也可以使用連結範本,將多個範本合併為單一部署流程。