diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index d9d66a78..f0042e46 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -5,6 +5,7 @@ **新機能:** - `config/profiles.yaml`と`config/default_profile.yaml`の設定ファイルで、出力内容をカスタマイズできる。 (#165) (@hitenkoku) +- 対象のフィールドがレコード内に存在しないことを確認する `null` キーワードに対応した。 (#643) (@hitenkoku) **改善:** diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f293b9e..a14081c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,14 @@ **New Features:** -- Customizable output of fields defined at `config/profiles.yaml` and `config/default_profile.yaml` (#165) (@hitenkoku) +- Customizable output of fields defined at `config/profiles.yaml` and `config/default_profile.yaml`. (#165) (@hitenkoku) +- Implemented the `null` keyword for rule detection. It is used to check if a target field exists or not. (#643) (@hitenkoku) **Enhancements:** - Removed ./ from rule path when updating. (#642) (@hitenkoku) - Added new output alias for MITRE ATT&CK tags and other tags. (#637) (@hitenkoku) -- Changed output summary numbers from without commas to with commas. (#649) (@hitenkoku) +- Added commas to summary numbers to make them easier to read. (#649) (@hitenkoku) **Bug Fixes:** diff --git a/src/detections/rule/matchers.rs b/src/detections/rule/matchers.rs index 27d98c69..8dc94bc1 100644 --- a/src/detections/rule/matchers.rs +++ b/src/detections/rule/matchers.rs @@ -218,7 +218,7 @@ impl DefaultMatcher { }); } - /// YEAのルールファイルのフィールド名とそれに続いて指定されるパイプを、正規表現形式の文字列に変換します。 + /// Hayabusaのルールファイルのフィールド名とそれに続いて指定されるパイプを、正規表現形式の文字列に変換します。 /// ワイルドカードの文字列を正規表現にする処理もこのメソッドに実装されています。patternにワイルドカードの文字列を指定して、pipesにPipeElement::Wildcardを指定すればOK!! fn from_pattern_to_regex_str(pattern: String, pipes: &[PipeElement]) -> String { // パターンをPipeで処理する。 @@ -346,6 +346,17 @@ impl LeafMatcher for DefaultMatcher { return false; } + // yamlにnullが設定されていた場合 + if self.re.is_none() { + // レコード内に対象のフィールドが存在しなければ検知したものとして扱う + for v in self.key_list.iter() { + if recinfo.get_value(v).is_none() { + return true; + } + } + return false; + } + if event_value.is_none() { return false; } @@ -353,7 +364,7 @@ impl LeafMatcher for DefaultMatcher { let event_value_str = event_value.unwrap(); if self.key_list.is_empty() { // この場合ただのgrep検索なので、ただ正規表現に一致するかどうか調べればよいだけ - return self.re.as_ref().unwrap().is_match(event_value_str); + self.re.as_ref().unwrap().is_match(event_value_str) } else { // 通常の検索はこっち self.is_regex_fullmatch(event_value_str) @@ -1984,4 +1995,65 @@ mod tests { } } } + + #[test] + fn test_eq_field_null() { + // 値でnullであった場合に対象のフィールドが存在しないことを確認 + let rule_str = r#" + enabled: true + detection: + selection: + Channel: + value: Security + Takoyaki: + value: null + details: 'command=%CommandLine%' + "#; + + let record_json_str = r#" + { + "Event": {"System": {"EventID": 4103, "Channel": "Security", "Computer": "Powershell" }}, + "Event_attributes": {"xmlns": "http://schemas.microsoft.com/win/2004/08/events/event"} + }"#; + + let mut rule_node = parse_rule_from_str(rule_str); + match serde_json::from_str(record_json_str) { + Ok(record) => { + let keys = detections::rule::get_detection_keys(&rule_node); + let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys); + assert!(rule_node.select(&recinfo)); + } + Err(_) => { + panic!("Failed to parse json record."); + } + } + } + #[test] + fn test_eq_field_null_not_detect() { + // 値でnullであった場合に対象のフィールドが存在しないことを確認するテスト + let rule_str = r#" + enabled: true + detection: + selection: + EventID: null + details: 'command=%CommandLine%' + "#; + + let record_json_str = r#"{ + "Event": {"System": {"EventID": 4103, "Channel": "Security", "Computer": "Powershell"}}, + "Event_attributes": {"xmlns": "http://schemas.microsoft.com/win/2004/08/events/event"} + }"#; + + let mut rule_node = parse_rule_from_str(rule_str); + match serde_json::from_str(record_json_str) { + Ok(record) => { + let keys = detections::rule::get_detection_keys(&rule_node); + let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys); + assert!(!rule_node.select(&recinfo)); + } + Err(e) => { + panic!("Failed to parse json record.{:?}", e); + } + } + } }