Microsoft Sentinel でネットワーク機器のログを分析する

Microsoft Sentinel は Microsoft 365 のセキュリティ ソリューションのログとアラートを集約するのによく使われているのですが、他のことは不得意（あるいはできない）と思われていそうな空気を感じることが多々あって、たとえば **「ネットワーク機器のログ集めらんないんだよね？」** とよく言われるので **「そんなことないよ！」** ということで記事を書いています。
あと、**「ネットワークログはとりあえず集めてるけど使ってないんだよね」** ということがかなりあるので、Microsoft Sentinel にはそういうとりあえず集めたログから脅威  (IOC/IOA)  を自動的に検出してくれる機能もついています。

この記事には次のことが書いてあります。

1. **Syslog** を Microsoft Sentinel に集める
2. **CEF** を使ってネットワーク機器のログを Microsoft Sentinel に集める
3. DCR を使って好みではないログを加工する
4. ログから自動的に新たな脅威が検出される仕組み

※ Sentinel が有効になった Log Analytics ワークスペースがあることを前提にしています。
## Syslog を Microsoft Sentinel に集める

これは細かくいうと Microsoft Sentinel ではなくて Azure Monitor の機能ですが、データ収集ルール (Data Collection Rule / DCR) を使って Windows や Linux マシンからログを集めることができます。
Azure VM の場合は特に準備は要らないのですが、Azure 以外のマシンではまず Azure Arc にオンボードする必要があります。では適当な VM をオンボードしましょう。準備したホストが Azure VM であればこの手順は不要です。

### Azure Arc へのオンボード

1. Azure ポータルで Azure Arc を開き、[マシン] - [追加/作成] - [マシンの追加] を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/43293bbc-4153-3b7c-20ff-13c9393658be.png)
 
2. Generate Script を選択し、必要なフィールドを入力します。Operating System は Linux を選択してください。プロキシ サーバーや閉域網を経由してデータを集めることもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/4511c623-4c53-c512-258d-f95b6442c4ad.png)

3. [Download and run script] を選ぶとオンボーディングのスクリプトが表示されるので、ダウンロードまたはコピーして Linux マシンで実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/f299aa98-a243-a52c-2c8f-4f51f64d6ed1.png)

4. スクリプトの実行が終了すると次のように URL (https://microsoft.com/devicelogin) と９桁のコードが表示されるので、URL を開き、コードを入力してください。資格情報を入力すると Linux マシンが Arc にオンボードされます。
```bash
...
GNU/Linux:2023.3. For supported OSs, see https://learn.microsoft.com/en-us/azure/azure-arc/servers/prerequisites#supported-operating-systems
INFO    Connecting machine to Azure... This might take a few minutes.
INFO    Testing connectivity to endpoints that are needed to connect to Azure... This might take a few minutes.
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate.
```

### データ収集ルールの作成

データ収集ルールは Azure Monitor の画面から作成します。
1. データ収集ルールから [作成] を選択します。
1. [基本] タブ では [プラットフォームの種類] に `Linux` を選択、その他は任意の項目を設定します。
1. [リソース] タブ では syslog を集めるマシンを追加します。Azure VM や、Azure Arc にオンボードされたマシンを選ぶことができます。
1. [収集と配信] タブで [データソースの追加] を選択し、[データソースの種類] に `Linux Syslog` を、ターゲットに Microsoft Sentinel が有効化されている Log Analytics ワークスペースを指定します。本来は集めるファシリティとログレベルに必要なものを指定しますが、今回は一旦動作を見たいので既定（全部あつめる）で構成してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/4899854d-f5de-11c2-bb4a-0468ee449a84.png)
1. [確認と作成] タブで [作成] を選択します。

### Syslog 取り込みの確認

Syslog が有効になった Linux マシンで次のコマンドを実行してみます。
```bash
 echo -n "<14> test syslog message" | nc -u -w0 localhost 514
```
5 分ほど待って、Microsoft Sentinel のログで次の KQL を実行してみます。

```kql
Syslog
| where SyslogMessage contains "test"
| top 100 by TimeGenerated desc 
```
このようなログが記録されます。`Facility` が `user`、`SeverityLevel` に `info`が設定されていて、`SyslogMessage` にはコマンドで指定した文字列が表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/5c5b8fd9-fccc-34be-519e-7a581b4e9e5f.png)

似たようなコマンドですが、次のコマンドも Linux マシンで試してみてください。
今度は`Facility` が `local7`、`SeverityLevel` が ` warning` に設定されたログが記録されるはずです。

```bash
 echo -n "<188> test syslog message" | nc -u -w0 localhost 514
```

**<括弧>** で囲まれた数字は Syslog の Priority と呼ばれる値で、ファシリティと重要度の組み合わせで作られます。この情報は Syslog テーブルの Facility と SevelityLevel 列に保持されれ、集められた情報がどのファシリティのどの重要度かを Microsoft Sentinel でも見分けることができます。

どの数字が何の意味か？については [RFC 3164](https://datatracker.ietf.org/doc/html/rfc3164) などに記載がありますが、[Broadcom のサイト](https://techdocs.broadcom.com/us/en/symantec-security-software/identity-security/privileged-access-manager/4-0/reference/messages-and-log-formats/syslog-message-formats/syslog-priority-facility-severity-grid.html) にある表がわかりやすいです。
例えば最初のコマンドの 14 は (user=1 * 8 + infor=6)=14、２つめだと (local7=23 * 8 + warining=4)=188 という計算です。

## CEF を使ってネットワーク機器のログを Microsoft Sentinel に集める

### データコネクタの作成

CEF の取り込みは Microsoft Sentinel のデータコネクタを使います。
1.  Microsoft Sentinel のコンテンツ ハブで [common event format] という名前のソリューションを探し、インストールします
1.  データ コネクタで [AMA による Common Event Format (CEF) (プレビュー)] を選択し、コネクタのページを開きます
1.  [データ収集ルールの作成] を選択し、[基本] に任意の情報を入力し、[リソース] で Syslog を設定したものと 同じ Linux マシンを指定します。
1.  [収集] で CEF が使用する `Facility` とログレベル指定します。最終的にはログを収集したいネットワーク機器に依存しますが、一旦は LOG_USER と LOG_DEBUG  で良いはずです。以下 LOG_USER を設定したものとして進めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/e1a68bc3-e731-4385-6aaa-04b13d522d1a.png)

1.  [確認と作成] に進み、コネクタを作成します。
1.  コネクタページの **[次のコマンドを実行して、CEF コレクターをインストールして適用します]** と書かれているコマンドを Linux マシンで実行します。 

データコネクタの構成は以上で完了です。

### CEF を送ってみる

[AMA コネクタで CEF ログをストリーミングする](https://learn.microsoft.com/ja-jp/azure/sentinel/connect-cef-ama#test-the-connector) を参考に、Linux マシンで次のコマンドを実行してみます。CEF というのはデータフォーマットで Syslog が実際にデータを転送するための仕組みです。Syslog の時と同じで最初の <14> が Priority となり、ファシリティ USER と 重要度 Information を指定しています。データコネクタでは USER の DEBUG 以上のログの収集を指定しているので、この Syslog は CEF コネクタによる収集の対象になります。

```bash
echo -n "<14>CEF:0|Mock-test-with-extension|MOCK|common-event-format-test|end|TRAFFIC|1|rt=$common=event-formatted-receive_time|SourceIP=192.168.100.100|DestinationIP=172.199.100.10|ProcessName=bash" | nc -u -w0 localhost 514
```
しばらくすると `CommonSecurityLog` テーブルに以下のようなログが表示されるはずです。CEF として処理されているのでログの文字列が `DeviceVendor` や `DeviceProduct` などとして解釈されているのと、それ以外のデータが `AdditionalExtensions` に保持されていることに注目してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/970d5139-d288-0d88-d862-8f04f6b8d729.png)

```nc -u -w0 localhost 514``` の部分を対象ホストの IP アドレスまたはホスト名にするとリモートから CEF を送ることができます。

```bash
echo -n "<14>CEF:0|Mock-test-with-extension-from-remote|MOCK|common-event-format-test|end|TRAFFIC|1|rt=$common=event-formatted-receive_time|SourceIP=192.168.100.100|DestinationIP=172.199.100.10|ProcessName=bash" | nc -u -w0 <your host address/name> 514
```
これで CEF を使ってログを受け取って Microsoft Sentinel にログを投入するためのデータコネクタができました。あとはネットワーク機器側で CEF や Syslog の設定を行います。おそらく設定の中で対象ホストとファシリティの指定が求められるので、このホストとファシリティ (USER) を指定します。機器で別のファシリティを使う必要がある、という場合には DCR でそのファシリティを設定してください。

一方 `Syslog` テーブルにも同じログが記録されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/b094aeaf-e288-fa58-af94-aa9e8ff4f508.png)

### Log が重複しないようにする

今回の構成では Syslog が全てのファシリティのログを収集していて、CEF は User ファシリティを指定する構成です。同じログを Syslog と CEF で重複させてどちらのテーブルでも参照したい場合にはこれで OK ですが、一般的なシナリオでは、より扱いやすい CEF だけがあればよく、Syslog は不要です。なので次のいずれかの方法で重複を避けます。

* Syslog の DCR で CEF で使用するファシリティを除外する
* Syslog の DCR で CEF のログだけを除外する

参考：[データ インジェストの重複を回避する](https://learn.microsoft.com/ja-jp/azure/sentinel/connect-cef-syslog#avoid-data-ingestion-duplication)

#### Syslog の DCR で CEF で使用するファシリティを除外する

CEF 以外に Syslog が必要なければ Azure Monitor の DCR からCEF のファシリティを除外します。

1. Azure Monitor の [データ収集ルール] から今回 Syslog 用に作成した DCR を開きます。
1. [データソース] で `Linux Syslog` を開きます。
1. データソースの [ファシリティ] で `LOG_USER` に `none` を設定し、保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/aa45c531-c1d9-b4c9-4a22-0ec3c0685f6f.png)

ついでに不要なファシリティや詳細すぎるログレベルがある場合にはここで `none` に設定してしまってください。

#### Syslog の DCR で CEF のログだけを除外する

CEF は使いたいものの「一部の Syslog は CEF が使用しているファシリティを使うかもしれない、、、」という場合には Syslog の DRC で変換ルールを構成して CEF のログを捨てるようにします。
これは１つの例ですが

1. Azure Monitor の [データ収集ルール] から今回 **Syslog** 用に作成した DCR を開きます。
1. [テンプレートのエクスポート]を選び、[デプロイ] を選択します。
1. [テンプレートの編集] を選ぶと ARM テンプレートを編集する画面になります。
1. 下の方にスクロールすると、このように dataFlows という項目があるので
```json
                "dataFlows": [
                    {
                        "streams": [
                            "Microsoft-Syslog"
                        ],
                        "destinations": [
                            "la-1507284852"
                        ]
                    }
                ]
```
transformKql という行を追加します。中ではデータ変換やフィルタを行う KQL を追加することができて、この例ではプロセス名に CEF が含まれるログを捨てるという処理を記述しています。「それだとまずい」という場合には他の条件を考えてください。
```json
                "dataFlows": [
                    {
                        "streams": [
                            "Microsoft-Syslog"
                        ],
                        "destinations": [
                            "la-1507284852"
                        ],
                        "transformKql": "source |where ProcessName !contains \"CEF\""
                    }
                ]
```

保存して[確認と作成] から [作成] を選択すると、以降 CEF のログは Syslog テーブルに含まれなくなります。

## DCR を使って好みではないログを加工する

上の手順では Syslog で特定のログを捨てるために DCR で transformKql を使いましたが、これを使ってログの加工を行うことができます。例えば CEF のテーブル `CommonSecurityLog` のログは `AdditionalExtension` に SourceIP や DestinationProcessName という文字列を含めていましたが、このデータを予め解析しながらデータを格納することができます。 

1. Azure Monitor の [データ収集ルール] から今回 **CEF** 用に作成した DCR を開きます。
1. [テンプレートのエクスポート]を選び、[デプロイ] を選択します。
1. [テンプレートの編集] を選ぶと ARM テンプレートを編集する画面になります。
1. `dataFlows` に次のような `transformKql`を追加します。
AdditionalExtentions の中身を取り出して対応するフィールドを追加するクエリです。なぜかイコールの後にセミコロン ; が追加されるので取り除く処理も行っています。
```json
                "dataFlows": [
                    {
                        "streams": [
                            "Microsoft-CommonSecurityLog"
                        ],
                        "destinations": [
                            "DataCollectionEvent"
                        ],
                        "transformKql": "source | extend DestinationIP = extract(@'DestinationIP=;?(.*?)(\\|)', 1, AdditionalExtensions) |  extend SourceIP = extract(@'SourceIP=;?(.*?)(\\|)', 1, AdditionalExtensions)"
                    }
                ]
```
保存して[確認と作成] から [作成] を選択します。しばらくすると設定が反映されて、この DCR で集められたログが `CommonSecurityLog` テーブルに入るときには `SourceIP` と `DestinationIP` 列が自動的に追加されるようになります。過去のログは変換されないので新たにログを投入してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247864/88d60edc-ba62-8bef-a8d2-893fde64be4b.png)


これは一例ですが、transformKql では KQL を使って色んな処理ができるので、`project-away` 演算子を使用して不要なフィールドを除外したり、文字列を変更して個人情報をマスクする、などログをいろいろと加工することができます。

## ログから脅威を自動的に検出する仕組み

Syslog や CEF を Microsoft Sentinel にログとして取り込むと、既定のルールを使用した脅威検出を利用することができます。

* [異常検出分析ルール](https://learn.microsoft.com/ja-jp/azure/sentinel/work-with-anomaly-rules)
* [照合分析ルール](https://learn.microsoft.com/ja-jp/azure/sentinel/use-matching-analytics-to-detect-threats)

このうち、照合分析ルールがあまり知られていないので解説したいのですが、このルールはワークスペースの特定のログの特定のフィールドを、自動的に背後の Microsoft の脅威インテリジェンスと照合してくれます。脅威が見つかった場合に、`ThreatIntelligenceIndicator` や `SecurityAlert` など関連するテーブルにいくつかのログを作成するのでごく微量のコストが発生しますがほとんど気にしなても良いレベルです。

1. Microsoft Sentinel で [分析] - [Rule Template] を開きます。
1. `(Preview) Microsoft Defender Threat Intelligence Analytics` を選択し、[Create rule] を選びます。
1. ウィザードに従ってルールを作成します。

この分析ルールは今回設定したログだと、次のフィールドに怪しい可能性が高い IP や URL が含まれていた場合にインシデントを作成します。

* ファシリティが `cron` に設定されている `Syslog`
* CEF の `DestinationIP` と `RequestURL`

ネットワーク機器のログを集める際に、機器のログでこれらのフィールドが使われるように設定すると、Microsoft Sentinel の脅威検知も利用することができます。外部への通信を分析するものであるという点と、syslog の場合はファシリティが `cron` であるという点に注意してください。フォーマットが違う場合には DCR でログを変換することで、検出可能なログにすることができます。
様々なインテリジェンスをデータコネクタで取り込んで使っているという方はたくさんいらっしゃると思いますが、照合分析ルールもぜひ使ってみてください。他にも Windows Server DNS や Azure / Office の Activity ログが自動的に照合されます。