この記事は公開されてから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行目のParentImageはsourceProcessNameに書き換えられました。次に元々CommandLineというフィールド名だったものが20,24,29,33行目のようにdestinationServiceNameとdeviceCustomString1のフィールド名に書き換えられ、さらにOR条件で複製されました。最後に19行目のImageは条件付きのMappingにより、ルール内のcategory: process_creationのキー・バリューと条件が合致したので、NewProcessNameに書き換えられました。
==例 おわり==
話を元に戻して、続いてLog Source Mappingsです。こちらは、コンフィグファイルのlogsources内のcategory、product、serviceの値が、ルールファイルの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
categoryとproductの値が完全に一致しましたので、コンフィグファイルの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行目のproductとserviceの値がルールファイルのキー・バリューと一致しますので、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を役立ててみてください。