Rule Creation Readmeの和訳
@@ -41,13 +41,13 @@ sample-evtx: ./sample-evtx/EVTX-to-MITRE-Attack/TA0003-Persistence/T1098.xxx-Acc
|
||||
logsource: default
|
||||
ruletype: Hayabusa
|
||||
``````
|
||||
> #Author section
|
||||
> ## Author section
|
||||
* **author [required]**: Name of the author(s).
|
||||
* **contributor** [optional]: Name of any contributor(s) (anyone who made any minor corrections).
|
||||
* **creation_date [required]**: Date the rule was made.
|
||||
* **updated_date** [optional]: Date the rule was updated.
|
||||
|
||||
> #Alert section
|
||||
> ## Alert section
|
||||
* **title [required]**: Rule file title. This will also be the name of the alert that gets displayed so the briefer the better. (Should not be longer than 85 characters.)
|
||||
* **title_jp** [optional]: The title in Japanese.
|
||||
* output [optional]: The details of the alert that gets displayed. Please output any fields in the Windows event log that are useful for analysis. Fields are seperated by `" : "` (two spaces on both sides). Field placeholders are enclosed with a `%` (Example: `%MemberName%`) and need to be defined in `config\eventkey_alias.txt`. (Explained below.)
|
||||
@@ -55,35 +55,35 @@ ruletype: Hayabusa
|
||||
* **description** [optional]: A description of the rule. This does not get displayed so you can make this long and detailed.
|
||||
* **description_jp** [optional]: The description in Japanese.
|
||||
|
||||
> #Rule section
|
||||
> ## Rule section
|
||||
* **id [required]**: A randomly generated version 4 UUID used to uniquely identify the rule. You can generate one [here](https://www.uuidgenerator.net/version4).
|
||||
* **level [required]**: Severity level based on [sigma's definition](https://github.com/SigmaHQ/sigma/wiki/Specification). Please write one of the following: `informational`,`low`,`medium`,`high`,`critical`
|
||||
* **status[required]**: `stable` for tested rules and `testing` for rules that need to be tested.
|
||||
* **detection [required]**: The detection logic goes here. (Explained below.)
|
||||
* **falsepositives [required]**: The possibilities for false positives. For example: `system administrator`, `normal user usage`, `normal system usage`, `legacy application`, `security team`, `none`. If it is unknown, please write `unknown`.
|
||||
* **tags** [optional]: If the technique is a [LOLBINS/LOLBAS](https://lolbas-project.github.io/) technique, please add the `lolbas` tag. If the alert can be mapped to a technique in the [MITRE ATT&CK](https://attack.mitre.org/) framework, please add the tactic ID (Example: `attack.t1098`) and any applicable tactics below:
|
||||
* attack.impact -> Impact
|
||||
* attack.initial_access -> Initial Access
|
||||
* attack.execution -> Execution
|
||||
* attack.lateral_movement -> Lateral Movement
|
||||
* attack.persistence -> Persistence
|
||||
* attack.privilege_escalation -> Privilege Escalation
|
||||
* attack.reconnaissance -> Reconnaissance
|
||||
* attack.collection -> Collection
|
||||
* attack.command_and_control -> Command and Control
|
||||
* attack.credential_access -> Credential Access
|
||||
* attack.defense_evasion -> Defense Evasion
|
||||
* attack.discovery -> Discovery
|
||||
* attack.exfiltration -> Exfiltration
|
||||
* attack.resource_development -> Resource Development
|
||||
* `attack.impact` -> Impact
|
||||
* `attack.initial_access` -> Initial Access
|
||||
* `attack.execution` -> Execution
|
||||
* `attack.lateral_movement` -> Lateral Movement
|
||||
* `attack.persistence` -> Persistence
|
||||
* `attack.privilege_escalation` -> Privilege Escalation
|
||||
* `attack.reconnaissance` -> Reconnaissance
|
||||
* `attack.collection` -> Collection
|
||||
* `attack.command_and_control` -> Command and Control
|
||||
* `attack.credential_access` -> Credential Access
|
||||
* `attack.defense_evasion` -> Defense Evasion
|
||||
* `attack.discovery` -> Discovery
|
||||
* `attack.exfiltration` -> Exfiltration
|
||||
* `attack.resource_development` -> Resource Development
|
||||
* **references** [optional]: Any links to references.
|
||||
* **sample-evtx [required]**: File path or URL to an event log file that this rule will detect.
|
||||
* **logsource [required]**: The source of where the log comes from. Please specify one of the following:
|
||||
* `default`: For logs that are turned on in Windows by default.
|
||||
* `non-default`: For logs that need to be turned on through group policy, etc...
|
||||
* `non-default`: For logs that need to be turned on through group policy, security baselines, etc...
|
||||
* `sysmon`: Logs that require sysmon to be installed.
|
||||
* **non-default-setting** [optional]: Explanation of how to turn on the log setting for `non-default` log sources.
|
||||
* **ruletype [required]**: `Hayabusa` for hayabusa rules. Rules automatically converted from sigma will be `Sigma`.
|
||||
* **ruletype [required]**: `Hayabusa` for hayabusa rules. Rules automatically converted from sigma Windows rules will be `Sigma`.
|
||||
|
||||
# Detection field
|
||||
## Detection fundamentals
|
||||
@@ -298,8 +298,8 @@ detection:
|
||||
``````
|
||||
|
||||
The following two wildcards can be used.
|
||||
* `*`: Matches any string of zero or more characters. (Internally it is converted to the regular expression `. *`.)
|
||||
* `?`: Matches any single character. (Internally converted to the regular expression `. `.)
|
||||
* `*`: Matches any string of zero or more characters. (Internally it is converted to the regular expression `.*`)
|
||||
* `?`: Matches any single character. (Internally converted to the regular expression `.`)
|
||||
|
||||
About escaping wildcards:
|
||||
* Wildcards (`*` and `?`) can be escaped by using a backslash: `\*`, `\?`.
|
||||
@@ -334,7 +334,7 @@ Currently, the following keywords can be specified:
|
||||
* `allowlist`: rule will be skipped if there is any match found in the list of regular expressions in the file that you specify in this field.
|
||||
|
||||
### regexes and allowlist keywords
|
||||
Hayabusa has two built-in regular expression files:
|
||||
Hayabusa has two built-in regular expression files used for the `.\rules\hayabusa\default\alerts\System\7045_CreateOrModiftySystemProcess-WindowsService_MaliciousServiceInstalled.yml` file:
|
||||
* `./config/regex/detectlist_suspicous_services.txt`: to detect suspicious service names
|
||||
* `./config/regex/allowlist_legitimate_services.txt`: to allow legitimate services
|
||||
|
||||
@@ -344,7 +344,7 @@ You can also use different detectlist and allowlist textfiles that you create.
|
||||
Please refer to the built-in `./config/regex/detectlist_suspicous_services.txt` and `./config/regex/allowlist_legitimate_services.txt` when creating your own.
|
||||
|
||||
## condition
|
||||
With the notation we explained above, you can express AND and OR logic but it will be confusing if you are trying to define complex logic.
|
||||
With the notation we explained above, you can express `AND` and `OR` logic but it will be confusing if you are trying to define complex logic.
|
||||
When you want to make more complex rules, you should use the `condition` keyword as shown below.
|
||||
|
||||
``````
|
||||
@@ -470,50 +470,110 @@ This is the most basic pattern: `count() {operator} {number}`. The rule below wi
|
||||

|
||||
|
||||
# Rule creation advice
|
||||
1. **When possible, always specify the `Channel` name.** In the future, we may filter on channel names so your rule may be ignored if the proper `Channel` is not set.
|
||||
2. **When possible, always specify the `EventID`.** In the future, we may filter on channel names so your rule may be ignored if the proper `EventID` is not set.
|
||||
3. **Do not use multiple `selection` fields when it is not needed.** For example:
|
||||
1. **When possible, always specify `Channel` and `EventID` name.** In the future, we may filter on channel names and event IDs so your rule may be ignored if this is not set.
|
||||
|
||||
2. **Do not use multiple `selection` or `filter` fields when it is not needed.** For example:
|
||||
|
||||
Bad example:
|
||||
```
|
||||
detection:
|
||||
SELECTION_1:
|
||||
EventID: 4625
|
||||
SELECTION_2:
|
||||
LogonType: 3
|
||||
condition: SELECTION_1 and SELECTION_2
|
||||
SELECTION_1:
|
||||
Channnel: Security
|
||||
SELECTION_2:
|
||||
EventID: 4625
|
||||
SELECTION_3:
|
||||
LogonType: 3
|
||||
FILTER_1:
|
||||
SubStatus: "0xc0000064" #Non-existent user
|
||||
FILTER_2:
|
||||
SubStatus: "0xc000006a" #Wrong password
|
||||
condition: SELECTION_1 and SELECTION_2 and SELECTION_3 and not (FILTER_1 or FILTER_2)
|
||||
```
|
||||
|
||||
Good example:
|
||||
```
|
||||
detection:
|
||||
selection:
|
||||
EventID: 4625
|
||||
LogonType: 3
|
||||
condition: selection
|
||||
selection:
|
||||
Channel: Security
|
||||
EventID: 4625
|
||||
LogonType: 3
|
||||
filter:
|
||||
- SubStatus: "0xc0000064" #Non-existent user
|
||||
- SubStatus: "0xc000006a" #Wrong password
|
||||
condition: selection and not filter
|
||||
```
|
||||
|
||||
4. **Name any of your filtering selections `filter`, `filter_1`, `filter_2`, etc... and do not use excessive grouping.**
|
||||
1. **When you need multiple sections, please name the first section with channel and event ID information in the `section_basic_info` section and other selections with meaningful names after `section_` and `filter_`, or use the notation `section_1`, `filter_1`, etc... Also, please write comments to explain anything difficult to understand.**
|
||||
|
||||
Bad example:
|
||||
```
|
||||
detection:
|
||||
SELECTION_1:
|
||||
EventID: 4625
|
||||
SELECTION_2:
|
||||
LogonType: 3
|
||||
SELECTION_3:
|
||||
IpAddress: '-'
|
||||
condition: ((SELECTION_1 and SELECTION_2) and not (SELECTION_3))
|
||||
Takoyaki:
|
||||
Channel: Security
|
||||
EventID: 4648
|
||||
Naruto:
|
||||
TargetUserName|endswith: "$"
|
||||
IpAddress: "-"
|
||||
Sushi:
|
||||
SubjectUserName|endswith: "$"
|
||||
TargetUserName|endswith: "$"
|
||||
TargetInfo|endswith: "$"
|
||||
Godzilla:
|
||||
SubjectUserName|endswith: "$"
|
||||
Ninja:
|
||||
TargetUserName|re: "(DWM|UMFD)-([0-9]|1[0-2])$"
|
||||
IpAddress: "-"
|
||||
Daisuki:
|
||||
- ProcessName|endswith: "powershell.exe"
|
||||
- ProcessName|endswith: "WMIC.exe"
|
||||
condition: Takoyaki and Daisuki and not (Naruto and not Godzilla) and not Ninja and not Sushi
|
||||
```
|
||||
|
||||
Good example:
|
||||
```
|
||||
detection:
|
||||
selection:
|
||||
EventID: 4625
|
||||
LogonType: 3
|
||||
filter:
|
||||
IpAddress: '-'
|
||||
condition: selection and not filter
|
||||
selection_basic_info:
|
||||
Channel: Security
|
||||
EventID: 4648
|
||||
selection_TargetUserIsComputerAccount:
|
||||
TargetUserName|endswith: "$"
|
||||
IpAddress: "-"
|
||||
filter_UsersAndTargetServerAreComputerAccounts: #Filter system noise
|
||||
SubjectUserName|endswith: "$"
|
||||
TargetUserName|endswith: "$"
|
||||
TargetInfo|endswith: "$"
|
||||
filter_SubjectUserIsComputerAccount:
|
||||
SubjectUserName|endswith: "$"
|
||||
filter_SystemAccounts:
|
||||
TargetUserName|re: "(DWM|UMFD)-([0-9]|1[0-2])$" #Filter out default Desktop Windows Manager and User Mode Driver Framework accounts
|
||||
IpAddress: "-" #Don't filter if the IP address is remote to catch attackers who created backdoor accounts that look like DWM-12, etc..
|
||||
selection_SuspiciousProcess:
|
||||
- ProcessName|endswith: "powershell.exe"
|
||||
- ProcessName|endswith: "WMIC.exe"
|
||||
condition: selection_basic and selection_SuspiciousProcess and not (selection_TargetUserIsComputerAccount
|
||||
and not filter_SubjectUserIsComputerAccount) and not filter_SystemAccounts and not filter_UsersAndTargetServerAreComputerAccounts
|
||||
```
|
||||
|
||||
OK example:
|
||||
```
|
||||
detection:
|
||||
selection_1:
|
||||
Channel: Security
|
||||
EventID: 4648
|
||||
selection_2:
|
||||
TargetUserName|endswith: "$"
|
||||
IpAddress: "-"
|
||||
filter_1: #Filter system noise
|
||||
SubjectUserName|endswith: "$"
|
||||
TargetUserName|endswith: "$"
|
||||
TargetInfo|endswith: "$"
|
||||
filter_2:
|
||||
SubjectUserName|endswith: "$"
|
||||
filter_3:
|
||||
TargetUserName|re: "(DWM|UMFD)-([0-9]|1[0-2])$" #Filter out default Desktop Windows Manager and User Mode Driver Framework accounts
|
||||
IpAddress: "-" #Don't filter if the IP address is remote to catch attackers who created backdoor accounts that look like DWM-12, etc..
|
||||
selection_4:
|
||||
- ProcessName|endswith: "powershell.exe"
|
||||
- ProcessName|endswith: "WMIC.exe"
|
||||
condition: selection_1 and selection_4 and not (selection_2 and not filter_2) and not filter_3 and not filter_1
|
||||
```
|
||||
@@ -1,70 +1,131 @@
|
||||
# ルールファイル
|
||||
HayabusaはWindowsEventログの検知ルールをYAML形式のファイルに記載します。
|
||||
単なる文字列一致だけでなく、正規表現やANDやOR等の条件を組み合わせることができ、複雑な検知ルールも表現できるようになっています。
|
||||
ここではその検知ルールの書き方について説明します。
|
||||
Hayabusaの検知ルールは、[YAML](https://en.wikipedia.org/wiki/YAML) 形式で記述されています。
|
||||
単純な文字列のマッチングだけでなく、正規表現や`AND`、`OR`などの条件を組み合わせて複雑な検出ルールを表現することができます。
|
||||
本節では、Hayabusaの検知ルールの書き方について説明します。
|
||||
|
||||
# ルールファイルのフォーマット
|
||||
ルールファイルのフォーマットは下記の通りです。
|
||||
# ルールファイル形式
|
||||
記述例:
|
||||
|
||||
``````
|
||||
title: PowerShell Execution Pipeline
|
||||
description: This rule detect powershell execution pipeline.
|
||||
author: Zach Mathis
|
||||
#Author section
|
||||
author: Eric Conrad, Zach Mathis
|
||||
creation_date: 2020/11/08
|
||||
updated_date: 2021/11/26
|
||||
|
||||
#Alert section
|
||||
title: User added to local Administrators group
|
||||
title_jp: ユーザがローカル管理者グループに追加された
|
||||
output: 'User: %MemberName% : SID: %MemberSid% : Group: %TargetUserName%'
|
||||
output_jp: 'ユーザ: %MemberName% : SID: %MemberSid% : グループ名: %TargetUserName%'
|
||||
description: A user was added to the local Administrators group.
|
||||
description_jp: ユーザがローカル管理者グループに追加された。
|
||||
|
||||
#Rule section
|
||||
id: 611e2e76-a28f-4255-812c-eb8836b2f5bb
|
||||
level: high
|
||||
status: stable
|
||||
detection:
|
||||
selection:
|
||||
Event.System.EventID: 7040
|
||||
Event.System.Channel: System
|
||||
Channel: Security
|
||||
EventID: 4732
|
||||
TargetUserName: Administrators
|
||||
condition: selection
|
||||
falsepositives:
|
||||
- unknown
|
||||
level: medium
|
||||
output: 'command=%CommandLine%'
|
||||
creation_date: 2020/11/8
|
||||
updated_date: 2020/11/8
|
||||
- system administrator
|
||||
tags:
|
||||
- attack.persistence
|
||||
- attack.t1098
|
||||
references:
|
||||
- https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventid=4732
|
||||
sample-evtx: ./sample-evtx/EVTX-to-MITRE-Attack/TA0003-Persistence/T1098.xxx-Account manipulation/ID4732-User added to local admin groups.evtx
|
||||
logsource: default
|
||||
ruletype: Hayabusa
|
||||
``````
|
||||
> ## 著者名欄
|
||||
* **author [必須]**: 著者名(複数可)。
|
||||
* **contributor** [オプション]: 寄稿者の名前(細かい修正をした人)。
|
||||
* **creation_date [必須]**: ルールが作成された日付。
|
||||
* **updated_date** [オプション]: ルールが更新された日付。
|
||||
|
||||
* title [required]: ルールファイルのタイトルを入力します。
|
||||
* description [optional]: ルールファイルの説明を入力します。
|
||||
* author [optional]: ルールファイルの作者を入力します。
|
||||
* detection [required]: 検知ルールを入力します。
|
||||
* falsepositives [optional]: 誤検知に関する情報を入力します。例:unknown、system administrator、normal user usage、normal system usage、legacy application、security team等々。
|
||||
* level [optional]: リスクレベルを入力します。指定する値は`informational`,`low`,`medium`,`high`,`critical`のいづれかです。
|
||||
* output [required]: イベントログが検知した場合に表示されるメッセージを入力します。
|
||||
* creation_date [optional]: ルールファイルの作成日を入力します。
|
||||
* updated_date [optional]: ルールファイルの更新日を入力します。
|
||||
> ## アラートセクション
|
||||
* **title [必須]**: ルールファイルのタイトル。これは表示されるアラートの名前にもなるので、簡潔であるほどよいです。(85文字以下でなければなりません。)
|
||||
* **title_jp** [オプション]: 日本語のタイトルです。
|
||||
* output [オプション]: 表示されるアラートの詳細です。Windowsイベントログの中で解析に有効なフィールドがあれば出力してください。フィールドは `" : "` で区切られます(両側ともスペース2つ)。フィールドのプレースホルダは `%` で囲まれ (例: `%MemberName%`) 、`config_eventkey_alias.txt` で定義する必要があります。(以下で説明します)
|
||||
* **output_jp** [オプション]: 日本語の出力メッセージ。
|
||||
* **description** [オプション]: ルールの説明。これは表示されないので、長く詳細に記述することができます。
|
||||
* **description_jp** [オプション]: 日本語の説明文です。
|
||||
|
||||
# detectionの記法について
|
||||
## detectionの基本
|
||||
まず、detectionの基本的な書き方について説明します。
|
||||
> ## ルールセクション
|
||||
* **id [必須]**: ルールを一意に識別するために使用される、ランダムに生成されたバージョン4のUUIDです。 [ここ](https://www.uuidgenerator.net/version4) で生成することができます。
|
||||
* **level [必須]**: [sigmaルールの定義](https://github.com/SigmaHQ/sigma/wiki/Specification)に基づく重要度レベル。 以下のいずれかを記述してください。 `informational`,`low`,`medium`,`high`,`critical`
|
||||
* **status[必須]**: テスト済みのルールには `stable` を、テストが必要なルールには `testing` を指定します。
|
||||
* **detection [必須]**: 検出ロジックはここに入ります。(以下で説明します。)
|
||||
* **falsepositives [必須]**: 誤検知の可能性について記載を行います。例: `system administrator`, `normal user usage`, `normal system usage`, `legacy application`, `security team`, `none`。 不明な場合は `unknown` と記述してください。
|
||||
* **tags** [オプション]: もしその技術が[LOLBINS/LOLBAS](https://lolbas-project.github.io/)の技術であれば、`lolbas` タグを追加してください。アラートを[MITRE ATT&CK](https://attack.mitre.org/) フレームワークにマッピングできる場合は、戦術ID(例:`attack.t1098`)や以下に該当する戦術を追加してください。
|
||||
* `attack.impact` -> Impact
|
||||
* `attack.initial_access` -> Initial Access
|
||||
* `attack.execution` -> Execution
|
||||
* `attack.lateral_movement` -> Lateral Movement
|
||||
* `attack.persistence` -> Persistence
|
||||
* `attack.privilege_escalation` -> Privilege Escalation
|
||||
* `attack.reconnaissance` -> Reconnaissance
|
||||
* `attack.collection` -> Collection
|
||||
* `attack.command_and_control` -> Command and Control
|
||||
* `attack.credential_access` -> Credential Access
|
||||
* `attack.defense_evasion` -> Defense Evasion
|
||||
* `attack.discovery` -> Discovery
|
||||
* `attack.exfiltration` -> Exfiltration
|
||||
* `attack.resource_development` -> Resource Development
|
||||
* **references** [オプション]: 参考文献への任意のリンク。
|
||||
* **sample-evtx [必須]**: このルールが検出するイベントログファイルへのファイルパスまたはURL。
|
||||
* **logsource [必須]**: ログの出所。以下のいずれかを指定してください。
|
||||
* `default`: Windowsでデフォルトで有効になっているログの場合等
|
||||
* `non-default`: グループポリシーやセキュリティベースラインなどで有効にする必要があるログ用。
|
||||
* `sysmon`: sysmonのインストールが必要なログ。
|
||||
* **non-default-setting** [オプション]: `non-default` のログソースのログ設定をオンにする方法の説明です。
|
||||
* **ruletype [必須]**: Hayabusaルールには `Hayabusa` を指定します。SigmaのWindowsルールから自動変換されたルールは `Sigma` になります。
|
||||
|
||||
### AND条件とOR条件の書き方
|
||||
AND条件を記載する場合はYAMLのハッシュを用いて記載します。
|
||||
下記のようにdetectionを記載すると、以下`両方の条件を満たす`イベントログを検知します。
|
||||
* EventIDが`7040`に完全一致する
|
||||
* Channelが`System`に完全一致する
|
||||
# 検知フィールド
|
||||
## 検知の基礎知識
|
||||
まず、検出ルールの作り方の基本を説明します。
|
||||
|
||||
|
||||
### AND論理とOR論理の書き方
|
||||
ANDロジックを書くには、ネストされた辞書を使用します。
|
||||
以下の検出ルールでは、ルールがマッチするためには、**両方の条件**が真でなければならないと定義しています。
|
||||
|
||||
* イベントIDは `7040` であること。
|
||||
* チャンネルは `System` であること。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
Event.System.EventID: 7040
|
||||
Event.System.Channel: System
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
OR条件を記載する場合は配列を利用します。
|
||||
下記のようにdetectionを記載すると、以下`いずれの条件を満たす`イベントログを検知します。
|
||||
* EventIDが`7040`に完全一致する
|
||||
* Channelが`System`に完全一致する
|
||||
OR論理を記述するには、リスト(`- `で始まる辞書)を使用します。
|
||||
以下の検出ルールでは、**片方**の条件がトリガーされることになります。
|
||||
|
||||
* イベントIDは `7040` であること。
|
||||
|
||||
**または**
|
||||
* チャンネルは `System` であること。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
- Event.System.EventID: 7040
|
||||
- Event.System.Channel: System
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
また、下記のように記載することもできます。
|
||||
この場合、以下`両方の条件を満たす`イベントログを検知します。
|
||||
* EventIDが`7040`又は`7041`に完全一致する
|
||||
* Channelが`System`に完全一致する
|
||||
また、以下のように「AND」と「OR」の論理を組み合わせることも可能です。
|
||||
この場合、以下の2つの条件が両方成立したときにルールがマッチします。
|
||||
|
||||
* イベントID が `7040` **または** `7041` のどちらかであること。
|
||||
* チャンネルが `System` であること。
|
||||
|
||||
``````
|
||||
detection:
|
||||
@@ -73,10 +134,15 @@ detection:
|
||||
- 7040
|
||||
- 7041
|
||||
Event.System.Channel: System
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
### eventkey
|
||||
WindowsイベントログをXML形式で一部抜粋で出力すると、下記のようになります。ルールファイルの例に含まれる`Event.System.Channel`は、XMLの`<Event><System><Channel>System<Channel><System></Event>`を指しています。今回の例のように、XML形式のWindowsイベントログについて、入れ子になったXMLのタグに含まれる値をルールの条件に指定する場合、`.`でつなげて指定します。ルールファイルでは、この`.`でつなげた文字列をeventkeyと呼んでいます。
|
||||
### イベントキー
|
||||
以下は、Windowsイベントログの抜粋で、オリジナルのXMLでフォーマットしたものです。上記のルールファイルの例の `Event.System.Channel` フィールドは、オリジナルのXMLタグを参照しています。
|
||||
|
||||
`<Event><System><Channel>System<Channel><System></Event>`
|
||||
|
||||
ネストされたXMLタグはドット(`.`)で区切られたタグ名で置き換えられます。Hayabusaのルールでは、ドットでつながれたこれらのフィールド文字列は `eventkeys` と呼ばれます。
|
||||
|
||||
``````
|
||||
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>
|
||||
@@ -86,22 +152,27 @@ WindowsイベントログをXML形式で一部抜粋で出力すると、下記
|
||||
</System>
|
||||
<EventData>
|
||||
<Data Name='param1'>Background Intelligent Transfer Service</Data>
|
||||
<Data Name='param2'>自動的な開始</Data>
|
||||
<Data Name='param2'>auto start</Data>
|
||||
</EventData>
|
||||
</Event>
|
||||
``````
|
||||
|
||||
### eventkeyのalias
|
||||
`.`でつなげたeventkeyは長い文字列になってしまうことがあるため、hayabusaではeventkeyに対するエイリアスを使用できます。エイリアスは`config\eventkey_alias.txt`というファイルに定義されています。ファイルはCSV形式であり、aliasとevent_keyという列から構成されています。aliasにはエイリアスを定義し、event_keyには`.`でつなげたeventkeyを指定します。このエイリアスを用いると、最初に例に挙げたdetectionは以下のように書き換えることができます。
|
||||
#### イベントキーエイリアス
|
||||
`.`の区切りが多くて長いイベントキーが一般的であるため、Hayabusaはエイリアスを使って簡単に扱えるようにします。エイリアスは `config\eventkey_alias.txt`ファイルで定義されています。このファイルは `alias` と `event_key` のマッピングで構成される CSV ファイルです。以下に示すように、エイリアスを使用して上記のルールを書き直し、ルールを読みやすくすることができます。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
EventID: 7040
|
||||
Channel: System
|
||||
EventID: 7040
|
||||
condition: selection
|
||||
``````
|
||||
### XMLの属性(attribute)をルールの条件にする方法
|
||||
WindowsEventログをXML形式で出力すると、XMLの属性に値が設定されている場合もあります。下記の例だと、ProviderタグのNameがXMLの属性です。
|
||||
|
||||
#### 注意: 未定義のイベントキーエイリアスについて
|
||||
すべてのイベントキーエイリアスが `config\eventkey_alias.txt`で定義されているわけではありません。`output`(アラートの詳細)メッセージで正しいデータを取得しておらず、代わりに`%EventID%`のような結果を取得している場合、または検出ロジックの選択が正しく機能していない場合は、新しいエイリアスを使用して `config\eventkey_alias.txt`を更新する必要があります。
|
||||
|
||||
### 条件におけるXML属性の使用方法
|
||||
XML要素には、スペースを入れることで属性を設定することができます。例えば、以下の `Provider Name` の `Name` は `Provider` 要素のXML属性です。
|
||||
|
||||
````````````
|
||||
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>
|
||||
@@ -114,8 +185,7 @@ WindowsEventログをXML形式で出力すると、XMLの属性に値が設定
|
||||
</System>
|
||||
</Event>
|
||||
````````````
|
||||
|
||||
XMLの属性をeventkeyで指定するには、{eventkey}_attributes.{attribute_name}という形式で指定します。例えば、ProviderタグのName属性をルールファイルに指定する場合、下記のようになります。
|
||||
イベントキーのXML属性を指定するには、`{eventkey}_attributes.{attribute_name}`という形式を使います。例えば、ルールファイルの `Provider` 要素の `Name` 属性を指定する場合は、以下のようになります。
|
||||
|
||||
``````
|
||||
detection:
|
||||
@@ -123,23 +193,25 @@ detection:
|
||||
Channel: Security
|
||||
EventID: 4672
|
||||
Event.System.Provider_attributes.Name: 'Microsoft-Windows-Security-Auditing'
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
### grep検索
|
||||
hayabusaではeventkeyを指定せず、WindowsEventログに含まれる文字列にマッチするかどうかを判定する機能も用意されています。この機能をhayabusaではgrep検索と呼んでいます。
|
||||
Hayabusaではeventkeyを指定せず、WindowsEventログに含まれる文字列にマッチするかどうかを判定する機能も用意されています。この機能をHayabusaではgrep検索と呼んでいます。
|
||||
|
||||
grep検索をするには下記のようにdetectionを指定します。この場合、administrator又はpublicという文字列がWindowsEventログに含まれる場合に、条件に一致したものとして条件に一致したものとして処理されます。また、grep検索にはワイルドカードを指定することも可能です。
|
||||
grep検索をするには下記のようにdetectionを指定します。この場合、`mimikatz`または`metasploit`という文字列がWindowsEventログに含まれる場合に、条件に一致したものとして条件に一致したものとして処理されます。また、grep検索にはワイルドカードを指定することも可能です。
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
- administrator
|
||||
- public
|
||||
- `mimikatz`
|
||||
- `metasploit`
|
||||
``````
|
||||
|
||||
hayabusaでは内部的にWindowsEventログをJSON形式に変換して上で処理を行っています。そのため、XMLのタグをgrep検索でマッチさせることはできません。
|
||||
> ※ Hayabusaでは内部的にWindowsEventログをJSON形式に変換して上で処理を行っています。そのため、XMLのタグをgrep検索でマッチさせることはできません。
|
||||
|
||||
### イベントデータ
|
||||
Windowsのイベントログは、基本データ(イベントID、タイムスタンプ、レコードID、ログ名(チャンネル))が書き込まれる`System`部分と、イベントIDに応じて任意のデータが書き込まれる`EventData`部分の2つに分けられます。問題は、`EventData` にネストされたタグの名前がすべて `Data` であるため、これまで説明したイベントキーでは `SubjectUserSid` と `SubjectUserName` を区別できないことです。
|
||||
|
||||
### EventData
|
||||
WindowsEventログをXML形式で出力すると、EventDataというタグが使用されている場合があります。(EventDataタグは様々なEventIDのログで頻繁に利用されます。)このEventDataにネストされたタグの名前は全て`Data`となっており、ここまで説明してきたeventkeyではSubjectUserSidやSubjectUserNameを区別することができません。
|
||||
````````````
|
||||
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>
|
||||
<System>
|
||||
@@ -151,26 +223,27 @@ WindowsEventログをXML形式で出力すると、EventDataというタグが
|
||||
</System>
|
||||
<EventData>
|
||||
<Data Name='SubjectUserSid'>S-1-1-11-1111111111-111111111-1111111111-1111</Data>
|
||||
<Data Name='SubjectUserName'>hayabusa</Data>
|
||||
<Data Name='SubjectDomainName'>DESKTOP-HAYABUSA</Data>
|
||||
<Data Name='SubjectUserName'>Hayabusa</Data>
|
||||
<Data Name='SubjectDomainName'>DESKTOP-Hayabusa</Data>
|
||||
<Data Name='SubjectLogonId'>0x11111111</Data>
|
||||
</EventData>
|
||||
</Event>
|
||||
````````````
|
||||
|
||||
この問題に対応するため、eventkeyで`Data`の代わりに`Name`に指定されている値をeventkeyに指定できるようになっています。例えば、EventData内のSubjectUserNameとSubjectDomainNameをルールの条件とする場合、下記のように記載します。
|
||||
|
||||
この問題に対処するために、`Data Name`で割り当てられた値を指定することができます。例えば、EventData に含まれる `SubjectUserName` と `SubjectDomainName` をルールの条件として利用したい場合、以下のように記述することが可能です。
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
EventID: 7040
|
||||
Channel: System
|
||||
Event.EventData.SubjectUserName: hayabusa
|
||||
EventID: 7040
|
||||
Event.EventData.SubjectUserName: Hayabusa
|
||||
Event.EventData.SubjectDomainName: DESKTOP-HAYBUSA
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
### EventDataの特殊なパターン
|
||||
EventDataというタグにネストされたタグの中には、Name属性が存在しないタグもあります。
|
||||
### EventDataの異常なパターン
|
||||
`EventData` にネストされたいくつかのタグは `Name` 属性を持ちません。
|
||||
|
||||
``````
|
||||
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>
|
||||
<System>
|
||||
@@ -186,143 +259,328 @@ EventDataというタグにネストされたタグの中には、Name属性が
|
||||
</Event>
|
||||
``````
|
||||
|
||||
上記のようなイベントログを検知する場合、`EventData`というeventkeyを指定します。この場合、EventDataタグにネストされているName属性の指定されてないタグのうち、いずれか一つでも一致するタグがあれば、条件に一致したものとして処理されます。
|
||||
上記のようなイベントログを検出するには、`EventData`という名前のイベントキーを指定します。この場合、`Name`属性を持たないネストされたタグのいずれかがマッチする限り、条件はマッチします。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
Channel: Security
|
||||
EventID: 5379
|
||||
EventData: None
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
## パイプ
|
||||
eventkeyにはパイプを指定することができます。ここまで説明した書き方では完全一致しか表現できませんでしたが、パイプを使うことでより柔軟な検知ルールを記載できるようになります。下記の例ではCommandLineの値が`yamato.*hayabusa`という正規表現にマッチする場合、条件に一致したものとして処理されます。
|
||||
パイプは、以下のようにイベントキーと組み合わせて、文字列のマッチングに使用することができます。これまで説明した条件はすべて完全一致ですが、パイプを使うことで、より柔軟な検出ルールを記述することができます。以下の例では、`EventData`の値が正規表現 `[\s\S]*EngineVersion=2.0[\s\S]*` にマッチする場合、条件にマッチすることになります。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
EventID: 7040
|
||||
Channel: System
|
||||
CommandLine|re: yamato.*hayabusa
|
||||
Channel: Microsoft-Windows-PowerShell/Operational
|
||||
EventID: 400
|
||||
EventData|re: '[\s\S]*EngineVersion=2\.0[\s\S]*'
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
使用できるパイプの一覧です。なお、v1.0.0時点では、複数のパイプをつなげて使用することはできません。
|
||||
* startswith: 先頭一致
|
||||
* endswith: 後方一致
|
||||
* contains: 部分一致
|
||||
* re: 正規表現(正規表現の処理にはregexクレートを使用しています。正規表現の詳細記法についてはhttps://docs.rs/regex/1.5.4/regex/を参照してください。)
|
||||
パイプの後に指定できるものの一覧です。現時点では、Hayabusa は複数のパイプを連結することはサポートしていません。
|
||||
* startswith: 文字列を先頭からチェックします。
|
||||
* endswith: 文字列の末尾をチェックします。
|
||||
* contains: ある単語がデータ内に含まれているかどうかをチェックします。
|
||||
* re: 正規表現を使用します。(私たちは regex crate を使っているので、正しい正規表現の書き方については https://docs.rs/regex/1.5.4/regex/ のドキュメントを参照してください)。
|
||||
> 注意: 正規表現を使用するSigmaルールの中には、Rustが正規表現を使用する方法の違いにより、 検出に失敗するものがあります。
|
||||
|
||||
## ワイルドカード
|
||||
eventkeyに対応する値にはワイルドカードを指定することができます。下記の例ではCommandLineがhayabusaという文字列で始まっていれば、条件に一致したものとして処理されます。基本的にはsigmaルールのwildcardと同じ仕様になっています。
|
||||
イベントキーにワイルドカードを使用することができます。以下の例では、`ProcessCommandLine` が "malware" という文字列で始まる場合、このルールはマッチします。
|
||||
この仕様は、Sigmaルールのワイルドカードと基本的に同じです。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
EventID: 7040
|
||||
Channel: System
|
||||
CommandLine: hayabusa*
|
||||
Channel: Security
|
||||
EventID: 4688
|
||||
ProcessCommandLine: malware*
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
使用できるワイルドカードの一覧です。
|
||||
* `*`: 任意の0文字以上の文字列にマッチします。(内部的には`.*`という正規表現に変換されます。)
|
||||
* `?`: 任意の1文字にマッチします。(内部的には`.`という正規表現に変換されます。)
|
||||
以下の2つのワイルドカードを使用することができます。
|
||||
* `*`: 0文字以上の任意の文字列にマッチします。(内部的には正規表現 `.*` に変換されます)。
|
||||
* `?`: 任意の1文字にマッチします。(内部的には正規表現 `. ` に変換されます)。
|
||||
|
||||
ワイルドカードを使用する場合、下記のルールに則って解釈されます。
|
||||
* ワイルドカード(`*`と`?`)をエスケープするにはバックスラッシュ(`/`)を使用します。
|
||||
* ワイルドカードの直前に文字としてのバックスラッシュ(`/`)を使用する場合、`\\*`又は`\\?`と記載してください。
|
||||
* バックスラッシュを単体で使う分にはエスケープ不要です。
|
||||
ワイルドカードのエスケープについて
|
||||
* ワイルドカード(`*` and `?`)は、バックスラッシュでエスケープできます: `\*` と `\?`.
|
||||
* もし、ワイルドカードの直前にバックスラッシュを使用したい場合は、 `\\*` または `\\?` と記述してください。
|
||||
* バックスラッシュを単独で使用する場合は、エスケープは必要ありません。
|
||||
|
||||
## eventkeyにネストできるキーワード
|
||||
eventkeyには特定のキーワードをネストさせることができます。下記の例ではCommandLineの値が`aa*bb`というワイルドカードにマッチした上で文字列長が10以上である場合、条件に一致したものと処理されます。
|
||||
## イベントキー内のキーワードのネスト
|
||||
イベントキーは、特定のキーワードでネストすることができます。
|
||||
以下の例では、以下の場合にルールがマッチします。
|
||||
* `ServiceName` が `malicious-service` であるか、または `./config/regex/regexes_suspicous_service.txt` にある正規表現を含んでいる場合。
|
||||
* `ImagePath` は1000文字以上であること。
|
||||
* `ImagePath` は `allowlist` にマッチするものが一つもありません。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
EventID: 7040
|
||||
Channel: System
|
||||
CommandLine:
|
||||
value: aa*bb
|
||||
min_length: 10
|
||||
EventID: 7045
|
||||
ServiceName:
|
||||
- value: malicious-service
|
||||
- regexes: ./config/regex/detectlist_suspicous_services.txt
|
||||
ImagePath:
|
||||
min_length: 1000
|
||||
allowlist: ./config/regex/allowlist_legitimate_services.txt
|
||||
condition: selection
|
||||
``````
|
||||
|
||||
現状では下記のキーワードを指定できます。
|
||||
* value: 文字列による一致(ワイルドカードやパイプを指定することもできます)
|
||||
* min_length: 指定した文字数以上である場合、条件に一致したものとして処理されます。
|
||||
* regexes: 指定したファイルに記載された正規表現のリストにひとつでも一致すれば、`条件に一致した`ものとして処理されます。
|
||||
* allowlist: 指定したファイルに記載された正規表現のリストにひとつでも一致すれば、`条件に一致していない`ものとして処理されます。
|
||||
現在、指定できるキーワードは以下の通りです。
|
||||
* `value`: 文字列によるマッチング (ワイルドカードやパイプも指定可能)。
|
||||
* `min_length`: 指定された文字数以上の場合にマッチします。
|
||||
* `regexes`: このフィールドで指定したファイル内の正規表現のいずれかにマッチする場合にマッチします。
|
||||
* `allowlist`: このフィールドで指定したファイル内の正規表現のリストにマッチするものがある場合、ルールはスキップされます。
|
||||
|
||||
### regexesとallowlist
|
||||
hayabusaではregexesやallowlistを使用した組み込みのルールを用意しており、それらのルールはhayabusa/config/regex内にあるregexes_suspicous_service.txtとallowlist_legimate_serviceimage.txtを参照しています。これらのファイルを書き換えることで、参照する全てのルールの挙動を一度に変更することが可能です。
|
||||
### regexesとallowlistキーワード
|
||||
Hayabusaに`.\rules\hayabusa\default\alerts\System\7045_CreateOrModiftySystemProcess-WindowsService_MaliciousServiceInstalled.yml`のルールのために使う2つの正規表現ファイルが用意されています。
|
||||
* `./config/regex/detectlist_suspicous_services.txt`: 怪しいサービス名を検出するためのものです。
|
||||
* `./config/regex/allowlist_legitimate_services.txt`: 正規のサービスを許可するためのものです。
|
||||
|
||||
`regexes` と `allowlist` で定義されたファイルは、ルールファイル自体を変更することなく、それらを参照するすべてのルールの動作を変更するために編集することが可能です。
|
||||
|
||||
また、regexesやallowlistに指定するファイルは、ユーザーが独自に作成することも可能です。作成する場合、regexes_suspicous_service.txtとallowlist_legimate_serviceimage.txtを参考にしてください。
|
||||
また、自分で作成した異なる regexes と allowlist テキストファイルを使用することもできます。
|
||||
デフォルトの `./config/detectlist_suspicous_services.txt` と `./config/allowlist_legitimate_services.txt` を参考にして、独自のファイルを作成してください。
|
||||
|
||||
## condition
|
||||
これまでの記法を用いると、AND条件やOR条件を表現することができますが、ANDやOR等が複雑に入り組んだ条件を定義することは難しい場合があります。その場合、conditionというキーワードを使用することで、複雑な条件式を定義することができます。
|
||||
## 条件
|
||||
上記で説明した表記法では、`AND`や`OR`の論理を表現することができますが、複雑な論理を定義しようとすると混乱してしまうでしょう。
|
||||
より複雑なルールを作りたい場合は、以下のように `condition` キーワードを使用します。
|
||||
|
||||
``````
|
||||
detection:
|
||||
SELECTION_1:
|
||||
EventID: 3
|
||||
SELECTION_2:
|
||||
Initiated: 'true'
|
||||
SELECTION_3:
|
||||
DestinationPort:
|
||||
- '4444'
|
||||
- '666'
|
||||
SELECTION_4:
|
||||
Image: '*\Program Files*'
|
||||
SELECTION_5:
|
||||
DestinationIp:
|
||||
- 10.*
|
||||
- 192.168.*
|
||||
- 172.16.*
|
||||
- 127.*
|
||||
SELECTION_6:
|
||||
DestinationIsIpv6: 'false'
|
||||
condition: (SELECTION_1 and (SELECTION_2 and SELECTION_3) and not ((SELECTION_4 or (SELECTION_5 and SELECTION_6))))
|
||||
``````
|
||||
|
||||
`condition`には、以下の式を用いることができます。
|
||||
* `{expression1} and {expression2}`: {expression1} と {expression2} の両方を必要とする。
|
||||
* `{expression1} or {expression2}`: {expression1} または {expression2} のどちらかを必要とする
|
||||
* `not {expression}`: {expression} の論理を反転させる
|
||||
* `( {expression} )`: {expression} の優先順位を設定する。数学と同じ優先順位の論理に従う。
|
||||
|
||||
上記の例では、 `SELECTION_1`、` SELECTION_2`などの選択名が使用されていますが、次の文字 `a-z A-Z 0-9 _`のみが含まれている限り、任意の名前を付けることができます。
|
||||
> ただし、可能な限り読みやすくするために、 `selection_1`、` selection_2`、 `filter_1`、` filter_2`などの標準的な規則を使用してください。
|
||||
|
||||
## notロジック
|
||||
多くのルールは誤検出を引き起こすので、検索するシグネチャーの選択と同時に、誤検知が無いようにフィルターの選択をすることはよくあります。
|
||||
|
||||
例えば
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
Channel: Security
|
||||
EventID: 4673
|
||||
filter:
|
||||
- ProcessName: C:\Windows\System32\net.exe
|
||||
- ProcessName: C:\Windows\System32\lsass.exe
|
||||
- ProcessName: C:\Windows\System32\audiodg.exe
|
||||
- ProcessName: C:\Windows\System32\svchost.exe
|
||||
- ProcessName: C:\Windows\System32\mmc.exe
|
||||
- ProcessName: C:\Windows\System32\net.exe
|
||||
- ProcessName: C:\Windows\explorer.exe
|
||||
- ProcessName: C:\Windows\System32\SettingSyncHost.exe
|
||||
- ProcessName: C:\Windows\System32\sdiagnhost.exe
|
||||
- ProcessName|startswith: C:\Program Files
|
||||
- SubjectUserName: LOCAL SERVICE
|
||||
condition: selection and not filter
|
||||
``````
|
||||
|
||||
## aggregation condition (集計条件) (別名: カウントルール)
|
||||
### 基本事項
|
||||
上記の `condition` キーワードは `AND` や `OR` ロジックを実装しているだけでなく、イベントをカウントしたり、「aggregate(集約)」したりすることも可能です。
|
||||
この機能は「集計条件」と呼ばれ、条件をパイプでつないで指定をします。
|
||||
以下の例では、24時間以内に任意の`ComputerName`に対して10個以上の `AccountName` 値があるかどうかを判断するために条件式が使用されています。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
Channel: Security
|
||||
EventID: 4648
|
||||
condition: selection | count(AccountName) by ComputerName >= 10
|
||||
timeframe: 24h
|
||||
``````
|
||||
|
||||
集計条件は以下の形式で定義することができます。
|
||||
* `count() {operator} {number}`: パイプの前の最初の条件にマッチするログイベントに対して、マッチしたログの数が `{operator}` と `{number}` で指定した条件式を満たす場合に条件がマッチします。
|
||||
|
||||
`{operator}` は以下のいずれかになります。
|
||||
* `==`: 指定された値と等しい場合、条件にマッチしたものとして扱われる。
|
||||
* `>=`: 指定された値以上であれば、条件にマッチしたものとして扱われる。
|
||||
* `>`: 指定された値以上であれば、条件にマッチしたものとして扱われる。
|
||||
* `<=`: 指定された値以下の場合、条件にマッチしたものとして扱われる。
|
||||
* `<`: 指定された値より小さい場合、条件にマッチしたものとして扱われる。
|
||||
|
||||
`{number}` は数値である必要があります。
|
||||
|
||||
`timeframe` は以下のように定義することができます。
|
||||
* `15s`: 15秒
|
||||
* `30m`: 30分
|
||||
* `12h`: 12時間
|
||||
* `7d`: 7日間
|
||||
* `3M`: 3ヶ月
|
||||
> `timeframe` は必須ではありませんが、パフォーマンスとメモリ効率のために、可能な限り定義することが強く推奨されます。
|
||||
|
||||
|
||||
### 集計条件として4パターン:
|
||||
1. count 引数または `by` キーワードを指定しない。例: `selection | count() > 10`
|
||||
> もし `selection` が時間枠内に10回以上マッチすれば、条件にマッチします。
|
||||
2. count 引数はないが、`by` キーワードはある。例: `selection | count() by Date > 10`
|
||||
> `selection` は**同じ**`Date` に対して10回以上 true になる必要があります。
|
||||
3. count 引数があるが、`by` キーワードがない場合。例: `selection | count(Users) > 10`
|
||||
> `selection` がマッチし、かつ `Users` が時間枠内で10回以上**異なる**場合であれば、条件にマッチします。
|
||||
4. count 引数と `by` キーワードの両方が存在する。例: `selection | count(Users) by Date > 10`
|
||||
> **同じ**「日付」に対して、条件が一致するためには、10人以上の**異なる**「ユーザ」が存在する必要があります。
|
||||
|
||||
|
||||
### パターン1の例:
|
||||
これは最も基本的なパターンです:`count() {operator} {number}`. 以下のルールは、`selection`が3回以上発生した場合にマッチします。
|
||||
|
||||

|
||||
|
||||
### パターン2の例:
|
||||
`count() by {eventkey} {operator} {number}`: パイプの前の `condition` にマッチするログイベントは、**同じ**`{eventkey}` でグループ化されます。各グループ化において、マッチしたイベントの数が `{operator}` と `{number}` で指定した条件を満たした場合、条件にマッチすることになります。
|
||||
|
||||

|
||||
|
||||
### パターン3の例:
|
||||
`count({eventkey}) {operator} {number}`: 条件パイプの前に、条件にマッチする `{eventkey}` の**異なる**値がいくつログイベント内に存在するかを数えます。その数が `{operator}` と `{number}` で指定された条件式を満たす場合、条件を満たしたものとみなします。
|
||||
|
||||

|
||||
|
||||
### パターン4の例:
|
||||
`count({eventkey_1}) by {eventkey_2} {operator} {number}`: 条件パイプの前にある条件にマッチしたログを**同じ**`{eventkey_2}` でグループ化し、各グループに含まれる `{eventkey_1}` の**異なる**値の数をカウントしています。各グループでカウントされた値が `{operator}` と `{number}` で指定された条件式を満たした場合、条件にマッチすることになります。
|
||||
|
||||

|
||||
|
||||
# ルール作成のアドバイス
|
||||
1. **可能な場合は、常に `Channel`と`EventID`を指定してください。** 将来的には、チャネル名とイベンドIDでフィルタリングする可能性があるため、適切な` Channel`と`EventID`が設定されていない場合はルールが無視される可能性があります。
|
||||
|
||||
2. **不要な場合は複数の `selection`と`filter`セクションを使用しないでください。**
|
||||
悪い例:
|
||||
```
|
||||
detection:
|
||||
detection:
|
||||
SELECTION_1:
|
||||
Channnel: Security
|
||||
SELECTION_2:
|
||||
EventID: 4625
|
||||
SELECTION_3:
|
||||
LogonType: 3
|
||||
FILTER_1:
|
||||
SubStatus: "0xc0000064"
|
||||
FILTER_2:
|
||||
SubStatus: "0xc000006a"
|
||||
condition: SELECTION_1 and SELECTION_2 and SELECTION_3 and not (FILTER_1 or FILTER_2)
|
||||
```
|
||||
|
||||
良い例:
|
||||
```
|
||||
detection:
|
||||
selection:
|
||||
Channel: Security
|
||||
EventID: 4625
|
||||
LogonType: 3
|
||||
filter:
|
||||
- SubStatus: "0xc0000064" #Non-existent user
|
||||
- SubStatus: "0xc000006a" #Wrong password
|
||||
condition: selection and not filter
|
||||
```
|
||||
|
||||
3. **複数のセクションが必要な場合は、チャンネル名とイベントIDの情報を記入する最初のセクションを `section_basic_info` セクションに、その他のセクションを `section_` と `filter_` の後に意味のある名前を付けるか、または `section_1`, `filter_1` などの記法を用いてください。また、分かりにくいところはコメントを書いて説明してください。**
|
||||
|
||||
悪い例:
|
||||
```
|
||||
detection:
|
||||
Takoyaki:
|
||||
Channel: Security
|
||||
EventID: 4648
|
||||
Naruto:
|
||||
TargetUserName|endswith: "$"
|
||||
IpAddress: "-"
|
||||
Sushi:
|
||||
SubjectUserName|endswith: "$"
|
||||
TargetUserName|endswith: "$"
|
||||
TargetInfo|endswith: "$"
|
||||
Godzilla:
|
||||
SubjectUserName|endswith: "$"
|
||||
Ninja:
|
||||
TargetUserName|re: "(DWM|UMFD)-([0-9]|1[0-2])$"
|
||||
IpAddress: "-"
|
||||
Daisuki:
|
||||
- ProcessName|endswith: "powershell.exe"
|
||||
- ProcessName|endswith: "WMIC.exe"
|
||||
condition: Takoyaki and Daisuki and not (Naruto and not Godzilla) and not Ninja and not Sushi
|
||||
```
|
||||
|
||||
良い例:
|
||||
```
|
||||
detection:
|
||||
selection_basic_info:
|
||||
Channel: Security
|
||||
EventID: 4648
|
||||
selection_TargetUserIsComputerAccount:
|
||||
TargetUserName|endswith: "$"
|
||||
IpAddress: "-"
|
||||
filter_UsersAndTargetServerAreComputerAccounts: #Filter system noise
|
||||
SubjectUserName|endswith: "$"
|
||||
TargetUserName|endswith: "$"
|
||||
TargetInfo|endswith: "$"
|
||||
filter_SubjectUserIsComputerAccount:
|
||||
SubjectUserName|endswith: "$"
|
||||
filter_SystemAccounts:
|
||||
TargetUserName|re: "(DWM|UMFD)-([0-9]|1[0-2])$" #Filter out default Desktop Windows Manager and User Mode Driver Framework accounts
|
||||
IpAddress: "-" #Don't filter if the IP address is remote to catch attackers who created backdoor accounts that look like DWM-12, etc..
|
||||
selection_SuspiciousProcess:
|
||||
- ProcessName|endswith: "powershell.exe"
|
||||
- ProcessName|endswith: "WMIC.exe"
|
||||
condition: selection_basic and selection_SuspiciousProcess and not (selection_TargetUserIsComputerAccount
|
||||
and not filter_SubjectUserIsComputerAccount) and not filter_SystemAccounts and not filter_UsersAndTargetServerAreComputerAccounts
|
||||
```
|
||||
|
||||
OKな例:
|
||||
```
|
||||
detection:
|
||||
selection_1:
|
||||
EventID: 7040
|
||||
Channel: Security
|
||||
EventID: 4648
|
||||
selection_2:
|
||||
EventID: 7041
|
||||
selection_3:
|
||||
Channel: System
|
||||
TargetUserName|endswith: "$"
|
||||
IpAddress: "-"
|
||||
filter_1: #Filter system noise
|
||||
SubjectUserName|endswith: "$"
|
||||
TargetUserName|endswith: "$"
|
||||
TargetInfo|endswith: "$"
|
||||
filter_2:
|
||||
SubjectUserName|endswith: "$"
|
||||
filter_3:
|
||||
TargetUserName|re: "(DWM|UMFD)-([0-9]|1[0-2])$" #Filter out default Desktop Windows Manager and User Mode Driver Framework accounts
|
||||
IpAddress: "-" #Don't filter if the IP address is remote to catch attackers who created backdoor accounts that look like DWM-12, etc..
|
||||
selection_4:
|
||||
CommandLine|contains: lsass.exe
|
||||
selection_5:
|
||||
CommandLine|contains: services.exe
|
||||
selection_6:
|
||||
ParentProcessName|contains: wininit.exe
|
||||
|
||||
condition: ( selection_1 or selection_2 ) and selection_3 and ( selection_4 or selection_5 ) and ( not selection_6 )
|
||||
``````
|
||||
|
||||
conditionには以下のキーワードを使用することができます。
|
||||
* {expression1} and {expression2}: {expression1}と{expression2}のAND条件を表します。
|
||||
* {expression1} or {expression2}: {expression1}と{expression2}のOR条件を表します。
|
||||
* not {expression}: {expression}の条件式の真偽を逆転させます。
|
||||
* ( {expression} ) : {expression}の条件式を優先して評価します。数学等で現れる括弧と同じです。
|
||||
|
||||
なお、上記の例では、条件式をグルーピングするためにselection_1やselection_2といった名前を使用していますが、selectionというprefixを付ける必要はなく、ユーザーが任意の名前を定義できます。ただし、使用可能な文字は`\w`という正規表現にマッチする文字のみです。
|
||||
|
||||
## aggregation condition
|
||||
上記で説明したconditionには、andやor条件だけでなく、検知したイベントログを集計するような機能も実装されています。この機能をaggregation conditionと呼んでおり、conditionの後にパイプでつなげて指定します。下記の例では、DestinationIpの値が3種類以上あるかどうかをSubjectUserName毎に判定する条件式になります。
|
||||
|
||||
``````
|
||||
detection:
|
||||
selection:
|
||||
EventID: 7040
|
||||
Channel: System
|
||||
condition: selection | count(DestinationIp) by SubjectUserName >= 3
|
||||
``````
|
||||
|
||||
aggregation conditionは下記の形式で定義できます。なお、{number}には数値を指定します。
|
||||
* `count() {operator} {number}`: conditionのパイプ以前の条件に一致したログについて、一致したログ数が{operator}と{number}で指定した条件式を満たす場合に、条件に一致したものとして処理されます。
|
||||
|
||||

|
||||
|
||||
* `count() by {eventkey_2} {operator} {number}`: conditionのパイプ以前の条件に一致したログを{eventkey_2}毎にグルーピングし、グルーピング毎に一致したログ数が{operator}と{number}で指定した条件式を満たす場合に、条件に一致したものとして処理されます。
|
||||
|
||||

|
||||
|
||||
* `count({eventkey}) {operator} {number}`: conditionのパイプ以前の条件に一致したログについて、{eventkey}の値が何種類存在するか数えます。その数が{operator}と{number}で指定した条件式を満たす場合に、条件に一致したものとして処理されます。
|
||||
|
||||

|
||||
|
||||
* `count({eventkey_1}) by {eventkey_2} {operator} {number}`: conditionのパイプ以前の条件に一致したログを{eventkey_2}毎にグルーピングし、そのグループ毎に{eventkey_1}の値が何種類存在するか数えます。そのグルーピング毎に数えた値が{operator}と{number}で指定した条件式を満たす場合に、条件に一致したものとして処理されます。
|
||||
|
||||

|
||||
|
||||
また、上記のoperatorには下記を指定できます。
|
||||
* `==`: 指定された値と等しい場合、条件に一致したものと処理されます。
|
||||
* `>=`: 指定された値以上である場合、条件に一致したものと処理されます。
|
||||
* `>`: 指定された値より大きい場合、条件に一致したものと処理されます。
|
||||
* `<=`: 指定された値以下である場合、条件に一致したものと処理されます。
|
||||
* `<`: 指定された値より小さい場合、条件に一致したものと処理されます。
|
||||
|
||||
# outputの記法
|
||||
detectionの条件に一致した場合に、出力されるメッセージを指定できます。固定の文字列が出力できる他、eventkeyを%で囲むことにより、検知したログの値を表示することも可能です。下記の例では検知した際のメッセージにScriptBlockTextというeventkeyの値を使用しています。
|
||||
|
||||
``````
|
||||
output: 'command=%ScriptBlockText%'
|
||||
``````
|
||||
- ProcessName|endswith: "powershell.exe"
|
||||
- ProcessName|endswith: "WMIC.exe"
|
||||
condition: selection_1 and selection_4 and not (selection_2 and not filter_2) and not filter_3 and not filter_1
|
||||
```
|
||||
BIN
doc/count1.png
|
Before Width: | Height: | Size: 56 KiB |
BIN
doc/count1_JP.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
doc/count2.png
|
Before Width: | Height: | Size: 55 KiB |
BIN
doc/count2_JP.png
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
doc/count3.png
|
Before Width: | Height: | Size: 82 KiB |
BIN
doc/count3_JP.png
Normal file
|
After Width: | Height: | Size: 167 KiB |
BIN
doc/count4.png
|
Before Width: | Height: | Size: 61 KiB |
BIN
doc/count4_JP.png
Normal file
|
After Width: | Height: | Size: 171 KiB |