SIEMクエリ変換ツール「Sigma」を使ってみた

2022.08.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

今回は、YARAやSnortのマルウェア/IPS検知ルールシグネチャを様々なSIEM製品の検索文に変換するツール「Sigma」を紹介したいと思います。

Sigmaとは

Sigmaは、セキュリティアナリストがSIEMを利用して悪性な痕跡を検出する際に必要なナレッジを標準化する目的により開発されました。YARAはファイルに対しての検知ルールであり、Snortはネットワークトラフィックに対する検知ルールでありますが、Sigmaではこれらをログイベントに対して適用可能なルールへと標準化しました。このルールを様々なSIEM製品で検索可能なクエリ文へと変換するコンバーターにより、SIEM製品で収集した様々なログイベントから、ログ監視を行うことができるようになります。

通常SIEM製品では、アナリストがセキュリティに関するホワイトペーパーやブログを基にイベントログから悪性な挙動を検出するためのクエリ文を作成し、テストを重ねた上で実装していくものですが、Sigmaによって一般化された検知ルールを、様々なSIEM製品に対応可能なクエリ文へと変換することでSIEM製品による強力な検知メカニズムを簡単に提供してくれます。ネットワークでのIDSとしてだったり、エンドポイントでのEDR、アプリケーションでのクエリパターン検知の補完的な検知メカニズムとしても使えますし、何よりSIEMの強みであるシステム間での相関関係を探っていくのに役立てることができます。
素晴らしいですね。

対応可能なSIEM製品

現時点で下記のSIEM製品に対応しています。かなりの数の製品に対応していることが分かりますね。(最新の対応製品については、この記事内で紹介するライブラリsigmac -lで確認できます)

  • Elasticsearch
  • OpenSearch
  • SQLite
  • Chronicle
  • CrowdStrike
  • Humio
  • Sumologic
  • ArcSight
  • Splunk
  • DNIF
  • Amazon Athena
  • NetWitness
  • QRadar
  • SQL
  • Azure Sentinel
  • grep
  • Sysmon
  • LimaCharlie
  • Graylog
  • FireEye Helix
  • Kibana
  • FortiSIEM
  • Datadog
  • Powershell
  • Lacework
  • uberAgent
  • LOGIQ
  • LogPoint
  • Carbon Black
  • Devo
  • Microsoft Defender Advanced Threat Protection (MDATP)
  • Qualys

使い方

SigmaはPythonベースでGithubレポジトリをクローン/ダウンロードして使うことができます。

git clone https://github.com/SigmaHQ/sigma

クローンするとrulesディレクトリ配下にSigmaの検知ルールファイルが格納されています。

またtoolsディレクトリの配下にはいくつかのPythonライブラリがあります。その中のsigmacがSigmaの検知ルールをSIEMの検索文にコンバートするためのファイルになります。

Sigma検知ルールファイル

まずrulesディレクトリ配下のSigmaの検知ルールファイルを見てみましょう。ルールについての説明が記載されたドキュメントはこちらになります。
試しにsigma/rules/windows/process_creation/proc_creation_win_susp_emotet_rundll32_execution.ymlを覗いてみます。
この検知ルールは2021年の年末から2022年8月現在も尚被害報告が相次いでいるEmotetに関連するものになります。

中身を見ながら、検知ルールの定義がどのようになっているか理解していきます。

ルールファイル - proc_creation_win_susp_emotet_rundll32_execution.yml

title: Emotet RunDLL32 Process Creation
id: 54e57ce3-0672-46eb-a402-2c0948d5e3e9
description: Detecting Emotet DLL loading by looking for rundll32.exe processes with command lines ending in ,RunDLL or ,Control_RunDLL
author: FPT.EagleEye
status: test
date: 2020/12/25
modified: 2021/11/17
references:
    - https://paste.cryptolaemus.com/emotet/2020/12/22/emotet-malware-IoCs_12-22-20.html
    - https://cyber.wtf/2021/11/15/guess-whos-back/
tags:
    - attack.defense_evasion
    - attack.t1218.011
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        Image|endswith: '\rundll32.exe'
        CommandLine|endswith:
            - ',RunDLL'
            - ',Control_RunDLL'
            # - ',#1'  too generic - function load by ordinal is not Emotet specific
    filter_legitimate_dll:
        CommandLine|endswith:
          - '.dll,Control_RunDLL'
          - '.dll",Control_RunDLL'
          - '.dll'',Control_RunDLL'
    filter_ide:
        ParentImage|endswith: '\tracker.exe' #When Visual Studio compile NodeJS program, it might use MSBuild to create tracker.exe and then, the tracker.exe fork rundll32.exe
    condition: selection and not filter_ide and not filter_legitimate_dll
falsepositives:
    - Unknown
level: critical

まずtitle(1行目)はその検知ルールの名前になります。次にdescription(3行目)を見てみます。翻訳すると、

Emotetを実行するために、rundll32.exeを ",RunDLL"または",Control_RunDLL"のパラメータが最後についたイベントを検知します。

rundll32.exeは正規なWindows実行ファイルですが、Emotetが実行される時には、同時にrundll32.exeを特定のパラメータをとって実行されるので、このパターンを持つログイベントをSIEMを使って検出すれば良いということになります。
tags(11行目)では、MITRE ATT&CKの識別子がつけられます。MITRE ATT&CKを参照することでこの検知がどの攻撃テクニックかも知ることができます。
logsource(14行目)はこの後に出てくるコンフィグファイルとの条件合致のために使われます。
detection(17行目)は最も重要で、上のdescription(3行目)に書かれていた内容を実現する検知ルールが書かれています。
検知ルールのそれぞれの項目は以下のようになっています。
selection(18行目)、filter_legitimate_dll(24行目)、filter_ide(29行目)は名前でcondition(31行目)内で利用されます。任意の名前でOKです。
selection(18行目)の中を見ていくと、Image|endwith(19行目)は「Image」フィールドの値が「\rundll32.exe」で終わるものを指しています。次に同じレベルでCommandLine|endswith(20行目)がきます。「CommandLine」フィールドの値が「,RunDLL」または「,Control_RunDLL」で終わるものを指しています。ここの「,RunDLL」と「,Control_RunDLL」は同じレベルのリストで先頭は"-"(ハイフン)で始まっていますが、ハイフンで始まる場合はORという意味になります。ハイフンがないものは全てANDを意味します。
Image|endwith(19行目)とCommandLine|endswith(20行目)は同じレベルでのリストになっていますが、ハイフンがないので、これらの2つの条件はANDになるわけです。
filter_legitimate_dll(24行目)とfilter_ide(29行目)の内側についても上記と同じように解釈していきます。
condition(31行目)を見ると「selection and not filter_ide and not filter_legitimate_dll」と書かれています。先程のselection(18行目)内での定義かつfilter_ide(24行目)内の定義ではないかつfilter_legitimate_dll(29行目)内の定義ではないものという条件を意味しています。つまり、filter_ide(24行目)とfilter_legitimate_dll(29行目)を既知の正規な動作として、検知ルールから除外しているかたちになります。
flasepositive(32行目)には誤検知が発生するケースが書かれていることがあります。
level(34行目)は「informational」、「low」、「medium」、「high」、「critical」の5段階が定義されます。

Sigma検知ルールをSIEMクエリにマッピングする

Sigma検知ルールをSIEMクエリにコンバートするためにコンフィグファイルを使って元のルールファイルのフィールドを書き換えたり条件を足したりしていきます。コンフィグファイルの中身を詳しく見ていく前に、簡単にsigmacコマンドについて確認しておきます。sigmacに関するドキュメントはこちらになります。

./tools/sigmac -h

上記コマンドでヘルプページを表示することができます。sigmacで一番重要なオプションが-tになります。これでコンバートする対象のSIEMをターゲットとして選択することができます。ヘルプオプションでも選択可能なターゲットを確認できますが、-lオプションでもシンプルな表示形式でターゲットを確認することも可能です。この後の手順では弊社でも取り扱っているSIEM製品「Sumo logic」をターゲットにして見ていこうと思います。
次に重要なオプションが-cになります。ここではコンバートするためのコンフィグファイルを指定することができます。このコンフィグファイルは、tools/configディレクトリにあらかじめ用意されています。ただヘルプでもあるように、-tオプションのみを与えてあげれば特別チューニングが必要でない場合以外は-cオプションは指定する必要がないような記載があります。ですので、コンバートしたい検知ルールを選んだら下記のように実行することでコンバートできます。(先程確認したEmotetの検知ルールを指定)

./tools/sigmac -t sumologic rules/windows/process_creation/proc_creation_win_susp_emotet_rundll32_execution.yml

しかし、-tで指定するターゲットによっては、-cオプションが必須のものもあるようなので、-tオプションだけでコンバートを実行してみて、怒られたら適切なコンフィグファイルを指定してあげてください。

ここで私が疑問に思ったのが、-tオプションのみを与えた時にどのコンフィグファイルを読み込んでコンバートを行っているのか?ということです。-tオプションのみを与えた時のコンフィグファイルの読み込み順の仕様については、GithubのREADMEなどに記載がされていなかったので、コンフィグファイルが保存されているtools/config配下のファイルを開いてみて、どういうロジックでコンフィグファイルが読まれているかあたりをつけながら検証してみました。
ターゲットを「sumologic」とした場合の検証結果からお伝えすると、最初にtools/config/generic配下の「sysmon.yml」コンフィグファイルを読み込んでから、tools/config配下の「sumologic.yml」コンフィグファイルを読み込んでいるようです。ただターゲットによってはtools/config/generic配下のファイルを読み込まず、backendsの値と、-tで指定したターゲットが一致するコンフィグファイルだけを暗黙的に読み込む挙動となったものもあったので、ご利用のSIEMをターゲットにした時の挙動について別途確認された方が良いと思います。
また、コンフィグファイルにはorderというキーがありますが、これは複数のコンフィグファイルが読み込まれた時に、先に読み込んだorderの値以上の数値を持つコンフィグファイルが後に読み込まれた場合に、後に読み込んだコンフィグファイルも評価されるようになります。orderの説明については一応ドキュメントにも記載がありました。
※ターゲットがsumologicの場合は-cでコンフィグファイルを指定した場合は、上記2種類のファイルを暗黙的に読み込む挙動にはならず、-cで指定したコンフィグファイルのみを参照するようになるようです。(-cで2種類以上のコンフィグファイルを明示してあげて読み込むことは可能)

では、sumologicの場合、./tools/sigmac -t sumologic rules/windows/process_creation/proc_creation_win_susp_emotet_rundll32_execution.ymlでコンバートした時にどのような仕組みでコンバートされていくのか見ていきます。

コンフィグファイルの定義についてはこちらのドキュメントに仕様が書かれています。

独自検証により、上記のコンバートだとまずtools/config/generic配下の「sysmon.yml」を読み込みます。

コンフィグファイル - sysmon.yml

title: Conversion of Generic Rules into Sysmon Specific Rules
order: 10
logsources:
    process_creation:
        category: process_creation
        product: windows
        conditions:
            EventID: 1
        rewrite:
            product: windows
            service: sysmon
    process_creation_linux:
        category: process_creation
        product: linux
        conditions:
            EventID: 1
        rewrite:
            product: linux
            service: sysmon
...
    sysmon_error:
        category: sysmon_error
        product: windows
        conditions:
            EventID: 255
        rewrite:
            product: windows
            service: sysmon

先程の説明の通りorderが「10」であることを確認しておきます。次にドキュメントのField Mappingsに記載のあるように、コンフィグファイル内にfieldmappingsがある場合に、その内側のフィールド名とルール内のフィールドが合致する場合に、フィールド名をコンフィグファイルの指定通りに書き換えます。「sysmon.yml」にはfieldmappingsはないのでこちらによる書き換えは起きません。
参考に例として以下のような「fieldmappings」を持つコンフィグファイルだったとします。

==例==

例コンフィグファイル

fieldmappings:
  ParentImage:
    - sourceProcessName
  CommandLine:
   - destinationServiceName
   - deviceCustomString1
  Image:
    service=security: Process
    category=process_creation: NewProcessName
    default: Image

「proc_creation_win_susp_emotet_rundll32_execution.yml」はfieldmappingsによって内部的に以下のように書き換えられます。

例ルールファイル - proc_creation_win_susp_emotet_rundll32_execution.yml

title: Emotet RunDLL32 Process Creation
id: 54e57ce3-0672-46eb-a402-2c0948d5e3e9
description: Detecting Emotet DLL loading by looking for rundll32.exe processes with command lines ending in ,RunDLL or ,Control_RunDLL
author: FPT.EagleEye
status: test
date: 2020/12/25
modified: 2021/11/17
references:
    - https://paste.cryptolaemus.com/emotet/2020/12/22/emotet-malware-IoCs_12-22-20.html
    - https://cyber.wtf/2021/11/15/guess-whos-back/
tags:
    - attack.defense_evasion
    - attack.t1218.011
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        NewProcessName|endswith: '\rundll32.exe'
        destinationServiceName|endswith:
            - ',RunDLL'
            - ',Control_RunDLL'
            # - ',#1'  too generic - function load by ordinal is not Emotet specific
        deviceCustomString1|endswith:
            - ',RunDLL'
            - ',Control_RunDLL'
            # - ',#1'  too generic - function load by ordinal is not Emotet specific
    filter_legitimate_dll:
        destinationServiceName|endswith:
          - '.dll,Control_RunDLL'
          - '.dll",Control_RunDLL'
          - '.dll'',Control_RunDLL'
        deviceCustomString1|endswith:
          - '.dll,Control_RunDLL'
          - '.dll",Control_RunDLL'
          - '.dll'',Control_RunDLL' 
    filter_ide:
        sourceProcessName|endswith: '\tracker.exe' #When Visual Studio compile NodeJS program, it might use MSBuild to create tracker.exe and then, the tracker.exe fork rundll32.exe
    condition: selection and not filter_ide and not filter_legitimate_dll
falsepositives:
    - Unknown
level: critical

まず、38行目のParentImagesourceProcessNameに書き換えられました。次に元々CommandLineというフィールド名だったものが20,24,29,33行目のようにdestinationServiceNamedeviceCustomString1のフィールド名に書き換えられ、さらにOR条件で複製されました。最後に19行目のImageは条件付きのMappingにより、ルール内のcategory: process_creationのキー・バリューと条件が合致したので、NewProcessNameに書き換えられました。
==例 おわり==

話を元に戻して、続いてLog Source Mappingsです。こちらは、コンフィグファイルのlogsources内のcategoryproductserviceの値が、ルールファイルのlogsourceの該当のキーと同じ値だった場合に、conditionの追加やフィールドの書き換えを行います。

ルールファイル「proc_creation_win_susp_emotet_rundll32_execution.yml」のlogsourceとコンフィグファイル「sysmon.yml」のlogsourcesに注目します。

ルールファイル - proc_creation_win_susp_emotet_rundll32_execution.yml

logsource:
    category: process_creation
    product: windows

コンフィグファイル - sysmon.yml

logsources:
    process_creation:
        category: process_creation
        product: windows
        conditions:
            EventID: 1
        rewrite:
            product: windows
            service: sysmon

categoryproductの値が完全に一致しましたので、コンフィグファイルのprocess_creation内の内容がルールに反映されます。

ルールファイル - proc_creation_win_susp_emotet_rundll32_execution.yml

title: Emotet RunDLL32 Process Creation
id: 54e57ce3-0672-46eb-a402-2c0948d5e3e9
description: Detecting Emotet DLL loading by looking for rundll32.exe processes with command lines ending in ,RunDLL or ,Control_RunDLL
author: FPT.EagleEye
status: test
date: 2020/12/25
modified: 2021/11/17
references:
    - https://paste.cryptolaemus.com/emotet/2020/12/22/emotet-malware-IoCs_12-22-20.html
    - https://cyber.wtf/2021/11/15/guess-whos-back/
tags:
    - attack.defense_evasion
    - attack.t1218.011
logsource:
    category: process_creation
    product: windows
    service: sysmon
detection:
    selection:
        Image|endswith: '\rundll32.exe'
        CommandLine|endswith:
            - ',RunDLL'
            - ',Control_RunDLL'
            # - ',#1'  too generic - function load by ordinal is not Emotet specific
    filter_legitimate_dll:
        CommandLine|endswith:
          - '.dll,Control_RunDLL'
          - '.dll",Control_RunDLL'
          - '.dll'',Control_RunDLL'
    filter_ide:
        ParentImage|endswith: '\tracker.exe' #When Visual Studio compile NodeJS program, it might use MSBuild to create tracker.exe and then, the tracker.exe fork rundll32.exe
    condition: selection and not filter_ide and not filter_legitimate_dll
    condition:
        EventID: 1
falsepositives:
    - Unknown
level: critical

「sysmon.yml」の読み込みが終わった後、続いて、「sumologic.yml」のコンフィグファイルが読み込まれます。

コンフィグファイル - sumologic.yml

title: SumoLogic
order: 20
backends:
  - sumologic
afl_fields:
  - _index
  - EventID
  - CommandLine
  - NewProcessName
  - Image
  - ParentImage
  - ParentCommandLine
  - ParentProcessName
# Sumulogic mapping depends on customer configuration. Adapt to your context!
# typically rule on _sourceCategory, _index or Field Extraction Rules (FER)
# supposing existing FER for service, EventChannel, EventID
logsources:
  unix:
    product: unix
    index: UNIX
...
  windows-sysmon:
    product: windows
    service: sysmon
    conditions:
      EventChannel: Microsoft-Windows-Sysmon
    index: WINDOWS
...
# if no index, search in all indexes

23行目、24行目のproductserviceの値がルールファイルのキー・バリューと一致しますので、conditionの追加やフィールドの書き換えが起こります。

ルールファイル - proc_creation_win_susp_emotet_rundll32_execution.yml

title: Emotet RunDLL32 Process Creation
id: 54e57ce3-0672-46eb-a402-2c0948d5e3e9
description: Detecting Emotet DLL loading by looking for rundll32.exe processes with command lines ending in ,RunDLL or ,Control_RunDLL
author: FPT.EagleEye
status: test
date: 2020/12/25
modified: 2021/11/17
references:
    - https://paste.cryptolaemus.com/emotet/2020/12/22/emotet-malware-IoCs_12-22-20.html
    - https://cyber.wtf/2021/11/15/guess-whos-back/
tags:
    - attack.defense_evasion
    - attack.t1218.011
logsource:
    category: process_creation
    product: windows
    service: sysmon
detection:
    selection:
        Image|endswith: '\rundll32.exe'
        CommandLine|endswith:
            - ',RunDLL'
            - ',Control_RunDLL'
            # - ',#1'  too generic - function load by ordinal is not Emotet specific
    filter_legitimate_dll:
        CommandLine|endswith:
          - '.dll,Control_RunDLL'
          - '.dll",Control_RunDLL'
          - '.dll'',Control_RunDLL'
    filter_ide:
        ParentImage|endswith: '\tracker.exe' #When Visual Studio compile NodeJS program, it might use MSBuild to create tracker.exe and then, the tracker.exe fork rundll32.exe
    condition: selection and not filter_ide and not filter_legitimate_dll
    condition:
        EventID: 1
    condition:
      EventChannel: Microsoft-Windows-Sysmon
falsepositives:
    - Unknown
level: critical

Sigma内部での話なので、おおよそ上記のような書き換えが起こっているという推測になりますが、これを基にSumo Logicのクエリ文がビルドされます。

% ./tools/sigmac -t sumologic rules/windows/process_creation/proc_creation_win_susp_emotet_rundll32_execution.yml
((EventID=1 AND "Microsoft-Windows-Sysmon") AND _sourceCategory=*windows* AND ((Image="*\rundll32.exe" AND (CommandLine = "*,RunDLL" OR CommandLine = "*,Control_RunDLL")) AND !(ParentImage="*\tracker.exe")) AND !((CommandLine = "*.dll,Control_RunDLL" OR CommandLine = "*.dl\",Control_RunDLL" OR CommandLine = "*.dll',Control_RunDLL")))

Sigmacの実行コマンドまで話を戻して、出力結果からSumo Logicのクエリ文を確認すると、上記のような仕組みでコンバーターがルールを変換してくれている様子が分かります。

まとめ

利用しているSIEMごとの環境によって、Sigmaの変換コマンドをどういう風に組み立てればいいかを理解することができました。
また、SIEM内の設計によって、「Index」だったり「Log Source」(一般的なSIEMで良く使われる用語・概念)の名前が変わってくることがあります。Sigmaのコンフィグファイルやルールファイルは自分で自由に修正することが可能なので、これらの設定ファイルをチューニングしつつ、環境にあったクエリ文を生成できそうです。

ぜひ、SIEM運用の際にSigmaを役立ててみてください。