From 7fe85e8142b20d1bb45ad4aa822bfceb7e4c83f2 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:06:53 +0900 Subject: [PATCH 1/3] feat(matchers): added cased modifier #1398 --- src/detections/rule/matchers.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/detections/rule/matchers.rs b/src/detections/rule/matchers.rs index acf4643db..506c6c045 100644 --- a/src/detections/rule/matchers.rs +++ b/src/detections/rule/matchers.rs @@ -482,6 +482,17 @@ impl LeafMatcher for DefaultMatcher { if !fastmatches.is_empty() { self.fast_match = Some(fastmatches); } + } else if self.pipes[1] == PipeElement::Cased { + if self.pipes[0] == PipeElement::Startswith { + self.fast_match = + Self::convert_to_fast_match(&format!("{}*", pattern[0]), false); + } else if self.pipes[0] == PipeElement::Endswith { + self.fast_match = + Self::convert_to_fast_match(&format!("*{}", pattern[0]), false); + } else if self.pipes[0] == PipeElement::Contains { + self.fast_match = + Self::convert_to_fast_match(&format!("*{}*", pattern[0]), false); + } } } else if n == 3 { if self.pipes.contains(&PipeElement::Contains) @@ -615,8 +626,20 @@ impl LeafMatcher for DefaultMatcher { let fast_match_result = if fast_matcher.len() == 1 { match &fast_matcher[0] { FastMatch::Exact(s) => Some(Self::eq_ignore_case(event_value_str, s)), - FastMatch::StartsWith(s) => Self::starts_with_ignore_case(event_value_str, s), - FastMatch::EndsWith(s) => Self::ends_with_ignore_case(event_value_str, s), + FastMatch::StartsWith(s) => { + if self.pipes.contains(&PipeElement::Cased) { + Some(event_value_str.starts_with(s)) + } else { + Self::starts_with_ignore_case(event_value_str, s) + } + } + FastMatch::EndsWith(s) => { + if self.pipes.contains(&PipeElement::Cased) { + Some(event_value_str.ends_with(s)) + } else { + Self::ends_with_ignore_case(event_value_str, s) + } + } FastMatch::Contains(s) | FastMatch::AllOnly(s) => { if self.pipes.contains(&PipeElement::Windash) { Some(utils::contains_str( @@ -625,6 +648,8 @@ impl LeafMatcher for DefaultMatcher { .to_lowercase(), s, )) + } else if self.pipes.contains(&PipeElement::Cased) { + Some(utils::contains_str(event_value_str, s)) } else { Some(utils::contains_str(&event_value_str.to_lowercase(), s)) } @@ -672,6 +697,7 @@ enum PipeElement { Cidr(Result), All, AllOnly, + Cased, } impl PipeElement { @@ -688,6 +714,7 @@ impl PipeElement { "cidr" => Option::Some(PipeElement::Cidr(IpCidr::from_str(pattern))), "all" => Option::Some(PipeElement::All), "allOnly" => Option::Some(PipeElement::AllOnly), + "cased" => Option::Some(PipeElement::Cased), _ => Option::None, }; From d6f5d6f8cc6b912074f04c44e6dc24669b6a46bf Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:07:28 +0900 Subject: [PATCH 2/3] test(matchers): added cased modirifer test #1398 --- src/detections/rule/matchers.rs | 221 ++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) diff --git a/src/detections/rule/matchers.rs b/src/detections/rule/matchers.rs index 506c6c045..093effa1c 100644 --- a/src/detections/rule/matchers.rs +++ b/src/detections/rule/matchers.rs @@ -1659,6 +1659,70 @@ mod tests { check_select(rule_str, record_json_str, false); } + #[test] + fn test_detect_startswith_cased() { + // startswith|casedが正しく検知できることを確認 + let rule_str = r#" + enabled: true + detection: + selection: + Channel: Security + EventID: 4732 + TargetUserName|startswith|cased: "Administrators" + details: 'user added to local Administrators UserName: %MemberName% SID: %MemberSid%' + "#; + + let record_json_str = r#" + { + "Event": { + "System": { + "EventID": 4732, + "Channel": "Security" + }, + "EventData": { + "TargetUserName": "AdministratorsTest" + } + }, + "Event_attributes": { + "xmlns": "http://schemas.microsoft.com/win/2004/08/events/event" + } + }"#; + + check_select(rule_str, record_json_str, true); + } + + #[test] + fn test_detect_startswith_cased2() { + // startswith|casedが正しく検知できることを確認 + let rule_str = r#" + enabled: true + detection: + selection: + Channel: Security + EventID: 4732 + TargetUserName|startswith|cased: "administrators" + details: 'user added to local Administrators UserName: %MemberName% SID: %MemberSid%' + "#; + + let record_json_str = r#" + { + "Event": { + "System": { + "EventID": 4732, + "Channel": "Security" + }, + "EventData": { + "TargetUserName": "AdministratorsTest" + } + }, + "Event_attributes": { + "xmlns": "http://schemas.microsoft.com/win/2004/08/events/event" + } + }"#; + + check_select(rule_str, record_json_str, false); + } + #[test] fn test_detect_endswith1() { // endswithが正しく検知できることを確認 @@ -1753,6 +1817,99 @@ mod tests { check_select(rule_str, record_json_str, false); } + #[test] + fn test_detect_endswith_cased1() { + // endswith|casedが正しく検知できることを確認 + let rule_str = r#" + enabled: true + detection: + selection: + Channel: Security + EventID: 4732 + TargetUserName|endswith|cased: "Administrators" + details: 'user added to local Administrators UserName: %MemberName% SID: %MemberSid%' + "#; + + let record_json_str = r#" + { + "Event": { + "System": { + "EventID": 4732, + "Channel": "Security" + }, + "EventData": { + "TargetUserName": "AdministratorsTest" + } + }, + "Event_attributes": { + "xmlns": "http://schemas.microsoft.com/win/2004/08/events/event" + } + }"#; + check_select(rule_str, record_json_str, false); + } + + #[test] + fn test_detect_endswith_cased2() { + // endswith|casedが正しく検知できることを確認 + let rule_str = r#" + enabled: true + detection: + selection: + Channel: Security + EventID: 4732 + TargetUserName|endswith|cased: "test" + details: 'user added to local Administrators UserName: %MemberName% SID: %MemberSid%' + "#; + + let record_json_str = r#" + { + "Event": { + "System": { + "EventID": 4732, + "Channel": "Security" + }, + "EventData": { + "TargetUserName": "AdministratorsTest" + } + }, + "Event_attributes": { + "xmlns": "http://schemas.microsoft.com/win/2004/08/events/event" + } + }"#; + check_select(rule_str, record_json_str, false); + } + + #[test] + fn test_detect_endswith_cased3() { + // endswith|casedが正しく検知できることを確認 + let rule_str = r#" + enabled: true + detection: + selection: + Channel: Security + EventID: 4732 + TargetUserName|endswith|cased: "sTest" + details: 'user added to local Administrators UserName: %MemberName% SID: %MemberSid%' + "#; + + let record_json_str = r#" + { + "Event": { + "System": { + "EventID": 4732, + "Channel": "Security" + }, + "EventData": { + "TargetUserName": "AdministratorsTest" + } + }, + "Event_attributes": { + "xmlns": "http://schemas.microsoft.com/win/2004/08/events/event" + } + }"#; + check_select(rule_str, record_json_str, true); + } + #[test] fn test_detect_contains1() { // containsが正しく検知できることを確認 @@ -1848,6 +2005,70 @@ mod tests { check_select(rule_str, record_json_str, false); } + #[test] + fn test_detect_contains_cased1() { + // contains|casedが正しく検知できることを確認 + let rule_str = r#" + enabled: true + detection: + selection: + Channel: Security + EventID: 4732 + TargetUserName|contains|cased: "Administrators" + details: 'user added to local Administrators UserName: %MemberName% SID: %MemberSid%' + "#; + + let record_json_str = r#" + { + "Event": { + "System": { + "EventID": 4732, + "Channel": "Security" + }, + "EventData": { + "TargetUserName": "TestAdministratorsTest" + } + }, + "Event_attributes": { + "xmlns": "http://schemas.microsoft.com/win/2004/08/events/event" + } + }"#; + + check_select(rule_str, record_json_str, true); + } + + #[test] + fn test_detect_contains_cased2() { + // contains|casedが正しく検知できることを確認 + let rule_str = r#" + enabled: true + detection: + selection: + Channel: Security + EventID: 4732 + TargetUserName|contains|cased: "MinistratorS" + details: 'user added to local Administrators UserName: %MemberName% SID: %MemberSid%' + "#; + + let record_json_str = r#" + { + "Event": { + "System": { + "EventID": 4732, + "Channel": "Security" + }, + "EventData": { + "TargetUserName": "TestministratorsTest" + } + }, + "Event_attributes": { + "xmlns": "http://schemas.microsoft.com/win/2004/08/events/event" + } + }"#; + + check_select(rule_str, record_json_str, false); + } + #[test] fn test_detect_wildcard_multibyte() { // multi byteの確認 From b01d24806ae521c4a60f2c098bcd49bc3a25f90e Mon Sep 17 00:00:00 2001 From: Yamato Security <71482215+YamatoSecurity@users.noreply.github.com> Date: Fri, 16 Aug 2024 19:49:58 +0900 Subject: [PATCH 3/3] update changelog --- CHANGELOG-Japanese.md | 10 ++++++++++ CHANGELOG.md | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index 31e8bcdf3..1a4c43c3c 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -2,6 +2,16 @@ ## 2.17.0 [2024/08/23] "HITCON Community Release" +**新機能:** + +- Sigma V2の`|re`のサブモディファイアに対応した。 submodifers. (#1399) (@fukusuket) + - 参考: https://github.com/SigmaHQ/sigma-specification/blob/main/appendix/sigma-modifiers-appendix.md + * `i`: (insensitive) 大文字小文字を区別しないマッチングを無効にする。 + * `m`: (multi-line) 複数行にまたがってマッチする。`^` /`$` は行頭/行末にマッチする。 + * `s`: (single-line) ドット文字 (`.`) は改行文字を含むすべての文字にマッチする。 +- Sigma V2の`|exists`モディファイアに対応した。 (#1400) (@hitenkoku) +- Sigma V2の`|cased`モディファイアに対応した。 (#1401) (@hitenkoku) + **改善:** - `cidr-utils`クレートを新バージョン0.6.xに対応した。 (#1366) (@hitenkoku) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d0aa1d9c..ac42e8e9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ ## 2.17.0 [2024/08/23] "HITCON Community Release" +**New Features:** + +- Support for the Sigma V2 `|re` submodifers. (#1399) (@fukusuket) + - Reference: https://github.com/SigmaHQ/sigma-specification/blob/main/appendix/sigma-modifiers-appendix.md + * `i`: (insensitive) disable case-sensitive matching. + * `m`: (multi-line) match across multiple lines. `^` /`$` match the start/end of line. + * `s`: (single-line) the dot character (`.`) matches all characters, including the newline character. +- Support for the Sigma V2 `|exists` modifier. (#1400) (@hitenkoku) +- Support for the Sigma V2 `|cased` modifier. (#1401) (@hitenkoku) + **Enhancements:** - Support for the newer version 0.6.x `cidr-utils` crate. (#1366) (@hitenkoku)