From b58ddcdfe6e3ddb8c26f9158158aeba43a6176a0 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:05:43 +0900 Subject: [PATCH 01/16] Renamed file name To be clearly output_tag.txt treat MitreTactics #637 --- config/{output_tag.txt => mitre_tactics.txt} | 0 src/detections/message.rs | 13 +++++++------ .../config/{output_tag.txt => mitre_tactics.txt} | 0 3 files changed, 7 insertions(+), 6 deletions(-) rename config/{output_tag.txt => mitre_tactics.txt} (100%) rename test_files/config/{output_tag.txt => mitre_tactics.txt} (100%) diff --git a/config/output_tag.txt b/config/mitre_tactics.txt similarity index 100% rename from config/output_tag.txt rename to config/mitre_tactics.txt diff --git a/src/detections/message.rs b/src/detections/message.rs index 92bf150c..214d0e8a 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -48,7 +48,7 @@ lazy_static! { pub static ref STATISTICS_FLAG: bool = configs::CONFIG.read().unwrap().args.statistics; pub static ref LOGONSUMMARY_FLAG: bool = configs::CONFIG.read().unwrap().args.logon_summary; pub static ref TAGS_CONFIG: HashMap = create_output_filter_config( - utils::check_setting_path(&CURRENT_EXE_PATH.to_path_buf(), "config/output_tag.txt") + utils::check_setting_path(&CURRENT_EXE_PATH.to_path_buf(), "config/mitre_tactics.txt") .to_str() .unwrap(), true, @@ -591,9 +591,10 @@ mod tests { ); } #[test] - /// test of loading output filter config by output_tag.txt - fn test_load_output_tag() { - let actual = create_output_filter_config("test_files/config/output_tag.txt", true, false); + /// test of loading output filter config by mitre_tactics.txt + fn test_load_mitre_tactics_log() { + let actual = + create_output_filter_config("test_files/config/mitre_tactics.txt", true, false); let expected: HashMap = HashMap::from([ ("attack.impact".to_string(), "Impact".to_string()), ("xxx".to_string(), "yyy".to_string()), @@ -602,9 +603,9 @@ mod tests { } #[test] - /// test of loading pass by output_tag.txt + /// test of loading pass by mitre_tactics.txt fn test_no_load_output_tag() { - let actual = create_output_filter_config("test_files/config/output_tag.txt", true, true); + let actual = create_output_filter_config("test_files/config/mitre_tactics.txt", true, true); let expected: HashMap = HashMap::new(); _check_hashmap_element(&expected, actual); } diff --git a/test_files/config/output_tag.txt b/test_files/config/mitre_tactics.txt similarity index 100% rename from test_files/config/output_tag.txt rename to test_files/config/mitre_tactics.txt From 3ef2845d8971c9ece0b87407980408ed0c32c45c Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:07:47 +0900 Subject: [PATCH 02/16] removed %MitreAttack% --- src/detections/detection.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 9dd8b065..b8a76d41 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -275,9 +275,6 @@ impl Detection { "%EventID%" => { profile_converter.insert("%EventID%".to_string(), eid.to_owned()); } - "%MitreAttack%" => { - profile_converter.insert("%MitreAttack%".to_string(), tag_info.join(" : ")); - } "%RecordID%" => { profile_converter.insert( "%RecordID%".to_string(), @@ -386,9 +383,6 @@ impl Detection { "%EventID%" => { profile_converter.insert("%EventID%".to_string(), "-".to_owned()); } - "%MitreAttack%" => { - profile_converter.insert("%MitreAttack%".to_owned(), tag_info.join(" : ")); - } "%RecordID%" => { profile_converter.insert("%RecordID%".to_string(), "".to_owned()); } From 3f186cb281165614d39c891e9c27029013e0f47a Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:08:35 +0900 Subject: [PATCH 03/16] Added separate feature Mitre ATT&CK tags and other tags when outputting #637 --- src/detections/detection.rs | 102 +++++++++++++++++++++++++++++++++--- src/options/profile.rs | 6 ++- 2 files changed, 100 insertions(+), 8 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index b8a76d41..2adf50d7 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -6,6 +6,7 @@ use crate::options::profile::{ LOAEDED_PROFILE_ALIAS, PRELOAD_PROFILE, PRELOAD_PROFILE_REGEX, PROFILES, }; use chrono::{TimeZone, Utc}; +use itertools::Itertools; use termcolor::{BufferWriter, Color, ColorChoice}; use crate::detections::message::AlertMessage; @@ -208,7 +209,7 @@ impl Detection { /// 条件に合致したレコードを格納するための関数 fn insert_message(rule: &RuleNode, record_info: &EvtxRecordInfo) { - let tag_info: Vec = Detection::get_tag_info(rule); + let tag_info: &Vec = &Detection::get_tag_info(rule); let recinfo = record_info .record_information .as_ref() @@ -316,6 +317,48 @@ impl Detection { .to_string(), ); } + "%MitreTactics%" => { + let tactics: &Vec = &tag_info.iter().filter(|x| TAGS_CONFIG.values().contains(x)).map(|y| { + y.to_owned() + }) + .collect(); + profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" : ")); + }, + "%MitreTechniques%" => { + let techniques: &Vec = &tag_info. + iter() + .filter(|x| { + !TAGS_CONFIG.values().contains(x) + && (x.starts_with("attack.t") + || x.starts_with("attack.g") + || x.starts_with("attack.s")) + }) + .map(|y| { + let mut replaced_tag = y.replace("attack.", ""); + let (head, _) = replaced_tag.split_at_mut(1); + head.make_ascii_uppercase(); + replaced_tag.to_owned() + }) + .collect(); + profile_converter + .insert("%MitreTechniques%".to_string(), techniques.join(" : ")); + }, + "%OtherTags%" => { + let tags: &Vec = &tag_info.iter() + .filter(|x| { + !(TAGS_CONFIG.values().contains(x) + || x.starts_with("attack.t") + || x.starts_with("attack.g") + || x.starts_with("attack.s")) + }) + .map(|y| { + y.to_owned() + }) + .collect(); + profile_converter + .insert("%OtherTags%".to_string(), tags.join(" : ")); + }, + _ => {} } } @@ -347,7 +390,7 @@ impl Detection { /// insert aggregation condition detection message to output stack fn insert_agg_message(rule: &RuleNode, agg_result: AggResult) { - let tag_info: Vec = Detection::get_tag_info(rule); + let tag_info: &Vec = &Detection::get_tag_info(rule); let output = Detection::create_count_output(rule, &agg_result); let rec_info = if LOAEDED_PROFILE_ALIAS.contains("%RecordInformation%") { Option::Some(String::default()) @@ -408,7 +451,48 @@ impl Detection { } "%EvtxFile%" => { profile_converter.insert("%EvtxFile%".to_string(), "-".to_owned()); - } + }, + "%MitreTactics%" => { + let tactics: &Vec = &tag_info.iter().filter(|x| TAGS_CONFIG.values().contains(x)).map(|y| { + y.to_owned() + }) + .collect(); + profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" : ")); + }, + "%MitreTechniques%" => { + let techniques: &Vec = &tag_info. + iter() + .filter(|x| { + !TAGS_CONFIG.values().contains(x) + && (x.starts_with("attack.t") + || x.starts_with("attack.g") + || x.starts_with("attack.s")) + }) + .map(|y| { + let mut replaced_tag = y.replace("attack.", ""); + let (head, _) = replaced_tag.split_at_mut(1); + head.make_ascii_uppercase(); + replaced_tag.to_owned() + }) + .collect(); + profile_converter + .insert("%MitreTechniques%".to_string(), techniques.join(" : ")); + }, + "%OtherTags%" => { + let tags: &Vec = &tag_info.iter() + .filter(|x| { + !(TAGS_CONFIG.values().contains(x) + || x.starts_with("attack.t") + || x.starts_with("attack.g") + || x.starts_with("attack.s")) + }) + .map(|y| { + y.to_owned() + }) + .collect(); + profile_converter + .insert("%OtherTags%".to_string(), tags.join(" : ")); + }, _ => {} } } @@ -441,8 +525,14 @@ impl Detection { .as_vec() .unwrap_or(&Vec::default()) .iter() - .filter_map(|info| TAGS_CONFIG.get(info.as_str().unwrap_or(&String::default()))) - .map(|str| str.to_owned()) + .map(|info| { + if let Some(tag) = TAGS_CONFIG.get(info.as_str().unwrap_or(&String::default())) + { + tag.to_owned() + } else { + info.as_str().unwrap_or(&String::default()).to_owned() + } + }) .collect(), true => rule.yaml["tags"] .as_vec() @@ -451,7 +541,7 @@ impl Detection { .map( |info| match TAGS_CONFIG.get(info.as_str().unwrap_or(&String::default())) { Some(s) => s.to_owned(), - _ => info.as_str().unwrap_or("").replace("attack.", ""), + _ => info.as_str().unwrap_or("").to_string() }, ) .collect(), diff --git a/src/options/profile.rs b/src/options/profile.rs index eddf5109..89bfa56c 100644 --- a/src/options/profile.rs +++ b/src/options/profile.rs @@ -36,12 +36,14 @@ lazy_static! { "%Channel%", "%Level%", "%EventID%", - "%MitreAttack%", "%RecordID%", "%RuleTitle%", "%RecordInformation%", "%RuleFile%", - "%EvtxFile%" + "%EvtxFile%", + "%MitreTactics%", + "%MitreTechniques%", + "%OtherTags%" ]; pub static ref PRELOAD_PROFILE_REGEX: RegexSet = RegexSet::new(&*PRELOAD_PROFILE).unwrap(); } From 2bb5bd4022db18d910cb8d9e687b03a3655f6ef7 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:10:32 +0900 Subject: [PATCH 04/16] added new tags in default_profile.yaml --- config/default_profile.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config/default_profile.yaml b/config/default_profile.yaml index 497101b0..69b60f19 100644 --- a/config/default_profile.yaml +++ b/config/default_profile.yaml @@ -4,7 +4,9 @@ Computer: "%Computer%" Channel: "%Channel%" Level: "%Level%" EventID: "%EventID%" -MitreAttack: "%MitreAttack%" +MitreAttack: "%MitreTactics%" +MitreTechnique: "%MitreTechniques%" +Tags: "%OtherTags%" RecordID: "%RecordID%" RuleTitle: "%RuleTitle%" Details: "%Details%" From 8ae2cf0bec62697201e515cb269add45b107f499 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:11:23 +0900 Subject: [PATCH 05/16] cargo fmt --- src/detections/detection.rs | 70 ++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 2adf50d7..9f6d57ed 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -318,20 +318,21 @@ impl Detection { ); } "%MitreTactics%" => { - let tactics: &Vec = &tag_info.iter().filter(|x| TAGS_CONFIG.values().contains(x)).map(|y| { - y.to_owned() - }) - .collect(); + let tactics: &Vec = &tag_info + .iter() + .filter(|x| TAGS_CONFIG.values().contains(x)) + .map(|y| y.to_owned()) + .collect(); profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" : ")); - }, + } "%MitreTechniques%" => { - let techniques: &Vec = &tag_info. - iter() + let techniques: &Vec = &tag_info + .iter() .filter(|x| { !TAGS_CONFIG.values().contains(x) && (x.starts_with("attack.t") - || x.starts_with("attack.g") - || x.starts_with("attack.s")) + || x.starts_with("attack.g") + || x.starts_with("attack.s")) }) .map(|y| { let mut replaced_tag = y.replace("attack.", ""); @@ -342,22 +343,20 @@ impl Detection { .collect(); profile_converter .insert("%MitreTechniques%".to_string(), techniques.join(" : ")); - }, + } "%OtherTags%" => { - let tags: &Vec = &tag_info.iter() + let tags: &Vec = &tag_info + .iter() .filter(|x| { !(TAGS_CONFIG.values().contains(x) || x.starts_with("attack.t") || x.starts_with("attack.g") || x.starts_with("attack.s")) }) - .map(|y| { - y.to_owned() - }) + .map(|y| y.to_owned()) .collect(); - profile_converter - .insert("%OtherTags%".to_string(), tags.join(" : ")); - }, + profile_converter.insert("%OtherTags%".to_string(), tags.join(" : ")); + } _ => {} } @@ -451,22 +450,23 @@ impl Detection { } "%EvtxFile%" => { profile_converter.insert("%EvtxFile%".to_string(), "-".to_owned()); - }, + } "%MitreTactics%" => { - let tactics: &Vec = &tag_info.iter().filter(|x| TAGS_CONFIG.values().contains(x)).map(|y| { - y.to_owned() - }) - .collect(); + let tactics: &Vec = &tag_info + .iter() + .filter(|x| TAGS_CONFIG.values().contains(x)) + .map(|y| y.to_owned()) + .collect(); profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" : ")); - }, + } "%MitreTechniques%" => { - let techniques: &Vec = &tag_info. - iter() + let techniques: &Vec = &tag_info + .iter() .filter(|x| { !TAGS_CONFIG.values().contains(x) && (x.starts_with("attack.t") - || x.starts_with("attack.g") - || x.starts_with("attack.s")) + || x.starts_with("attack.g") + || x.starts_with("attack.s")) }) .map(|y| { let mut replaced_tag = y.replace("attack.", ""); @@ -477,22 +477,20 @@ impl Detection { .collect(); profile_converter .insert("%MitreTechniques%".to_string(), techniques.join(" : ")); - }, + } "%OtherTags%" => { - let tags: &Vec = &tag_info.iter() + let tags: &Vec = &tag_info + .iter() .filter(|x| { !(TAGS_CONFIG.values().contains(x) || x.starts_with("attack.t") || x.starts_with("attack.g") || x.starts_with("attack.s")) }) - .map(|y| { - y.to_owned() - }) + .map(|y| y.to_owned()) .collect(); - profile_converter - .insert("%OtherTags%".to_string(), tags.join(" : ")); - }, + profile_converter.insert("%OtherTags%".to_string(), tags.join(" : ")); + } _ => {} } } @@ -541,7 +539,7 @@ impl Detection { .map( |info| match TAGS_CONFIG.get(info.as_str().unwrap_or(&String::default())) { Some(s) => s.to_owned(), - _ => info.as_str().unwrap_or("").to_string() + _ => info.as_str().unwrap_or("").to_string(), }, ) .collect(), From 3f25f951e76adc82668012217585fc0c9b806a01 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:24:32 +0900 Subject: [PATCH 06/16] Changed MitreTechniques alias to MitreTags due to MitreTags is included tags expect techniques. --- config/default_profile.yaml | 4 ++-- src/detections/detection.rs | 16 ++++++---------- src/options/profile.rs | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/config/default_profile.yaml b/config/default_profile.yaml index 69b60f19..f8fc4100 100644 --- a/config/default_profile.yaml +++ b/config/default_profile.yaml @@ -5,8 +5,8 @@ Channel: "%Channel%" Level: "%Level%" EventID: "%EventID%" MitreAttack: "%MitreTactics%" -MitreTechnique: "%MitreTechniques%" -Tags: "%OtherTags%" +MitreTags: "%MitreTags%" +OtherTags: "%OtherTags%" RecordID: "%RecordID%" RuleTitle: "%RuleTitle%" Details: "%Details%" diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 9f6d57ed..37772e35 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -325,7 +325,7 @@ impl Detection { .collect(); profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" : ")); } - "%MitreTechniques%" => { + "%MitreTags%" => { let techniques: &Vec = &tag_info .iter() .filter(|x| { @@ -336,13 +336,11 @@ impl Detection { }) .map(|y| { let mut replaced_tag = y.replace("attack.", ""); - let (head, _) = replaced_tag.split_at_mut(1); - head.make_ascii_uppercase(); - replaced_tag.to_owned() + make_ascii_titlecase(&mut replaced_tag) }) .collect(); profile_converter - .insert("%MitreTechniques%".to_string(), techniques.join(" : ")); + .insert("%MitreTags%".to_string(), techniques.join(" : ")); } "%OtherTags%" => { let tags: &Vec = &tag_info @@ -459,7 +457,7 @@ impl Detection { .collect(); profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" : ")); } - "%MitreTechniques%" => { + "%MitreTags%" => { let techniques: &Vec = &tag_info .iter() .filter(|x| { @@ -470,13 +468,11 @@ impl Detection { }) .map(|y| { let mut replaced_tag = y.replace("attack.", ""); - let (head, _) = replaced_tag.split_at_mut(1); - head.make_ascii_uppercase(); - replaced_tag.to_owned() + make_ascii_titlecase(&mut replaced_tag) }) .collect(); profile_converter - .insert("%MitreTechniques%".to_string(), techniques.join(" : ")); + .insert("%MitreTags%".to_string(), techniques.join(" : ")); } "%OtherTags%" => { let tags: &Vec = &tag_info diff --git a/src/options/profile.rs b/src/options/profile.rs index 89bfa56c..70e0e9cf 100644 --- a/src/options/profile.rs +++ b/src/options/profile.rs @@ -42,7 +42,7 @@ lazy_static! { "%RuleFile%", "%EvtxFile%", "%MitreTactics%", - "%MitreTechniques%", + "%MitreTags%", "%OtherTags%" ]; pub static ref PRELOAD_PROFILE_REGEX: RegexSet = RegexSet::new(&*PRELOAD_PROFILE).unwrap(); From f971510c0a63e736fd9a7e4c1c3723737c9bbad8 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:26:19 +0900 Subject: [PATCH 07/16] updated changelog #637 --- CHANGELOG-Japanese.md | 1 + CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index 5b6218f9..b79fafdc 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -9,6 +9,7 @@ **改善:** - ルールのアップデート機能のルールパスの出力から./を削除した。 (#642) (@hitenkoku) +- MITRE ATT&CK関連のタグとその他タグを出力するための出力用のエイリアスを追加した。 (#637) (@hitenkoku) **バグ修正:** diff --git a/CHANGELOG.md b/CHANGELOG.md index 8089771c..f27030c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ **Enhancements:** - Removed ./ from rule path when updating. (#642) (@hitenkoku) +- Added new output alias for MITRE ATT&CK tags and other tags. (#637) (@hitenkoku) **Bug Fixes:** From 99ad306de146b4f5047f48505063ec9f52480d9f Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:37:35 +0900 Subject: [PATCH 08/16] updated readme due to added new output alias --- README-1.4.3-Japanese.md | 8 ++++++-- README.md | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README-1.4.3-Japanese.md b/README-1.4.3-Japanese.md index f0b9504e..5ef935fe 100644 --- a/README-1.4.3-Japanese.md +++ b/README-1.4.3-Japanese.md @@ -509,7 +509,9 @@ Hayabusaの結果を標準出力に表示しているとき(デフォルト) * `Title`: YML検知ルールの`title`フィールドから来ています。 * `RecordID`: イベントレコードIDです。``フィールドから来ています。 * `Details`: YML検知ルールの`details`フィールドから来ていますが、このフィールドはHayabusaルールにしかありません。このフィールドはアラートとイベントに関する追加情報を提供し、ログのフィールドから有用なデータを抽出することができます。イベントキーのマッピングが間違っている場合、もしくはフィールドが存在しない場合で抽出ができなかった箇所は`n/a` (not available)と記載されます。YML検知ルールに`details`フィールドが存在しない時のdetailsのメッセージを`./rules/config/default_details.txt`で設定できます。`default_details.txt`では`Provider Name`、`EventID`、`details`の組み合わせで設定することができます。default_details.txt`やYML検知ルールに対応するルールが記載されていない場合はすべてのフィールド情報を出力します。 -* `MitreAttack`: MITRE ATT&CKの戦術。 +* `MitreTactics`: MITRE ATT&CKの戦術。 +* `MitreTags`: MITRE ATT&CKの戦術以外の情報。attack.g(グループ)、attack.t(技術)、attack.s(ソフトウェア)の情報を出力します。 +* `OtherTags`: YML検知ルールの`tags` フィールドから`MitreTactics`, `MitreTags` 以外の月情報を出力します。 * `RuleFile`: アラートまたはイベントを生成した検知ルールのファイル名。 * `EvtxFile`: アラートまたはイベントを起こしたevtxファイルへのパス。 * `RecordInformation`: すべてのフィールド情報。 @@ -527,7 +529,9 @@ default_profiles.txtをprofile.txtに書かれているプロファイルで上 |%Channel% | `Channel` | |%Level% | `Level` | |%EventID% | `EventID` | -|%MitreAttack% | `MitreAttack` | +|%MitreTactics% | `MitreTactics` | +|%MitreTags% | `MitreTags` | +|%OtherTags% | `OtherTags` | |%RecordID% | `RecordID` | |%RuleTitle% | `Title` | |%Details% | `Details` | diff --git a/README.md b/README.md index f6bfc1eb..2fa3e624 100644 --- a/README.md +++ b/README.md @@ -506,7 +506,9 @@ When hayabusa output is being displayed to the screen (the default), it can disp * `RecordID`: This comes from the `` field in the event log. * `Title`: This comes from the `title` field in the YML detection rule. * `Details`: This comes from the `details` field in the YML detection rule, however, only hayabusa rules have this field. This field gives extra information about the alert or event and can extract useful data from the fields in event logs. For example, usernames, command line information, process information, etc... When a placeholder points to a field that does not exist or there is an incorrect alias mapping, it will be outputted as `n/a` (not available). If the `details` field is not specified (i.e. sigma rules), default `details` messages to extract fields defined in `./rules/config/default_details.txt` will be outputted. You can add more default `details` messages by adding the `Provider Name`, `EventID` and `details` message you want to output in `default_details.txt`. When no `details` field is defined in a rule nor in `default_details.txt`, all fields will be outputted to the `details` column. -* `MitreAttack`: MITRE ATT&CK tactics. +* `MitreTactics`: MITRE ATT&CK tactics. +* `MitreTags`: MITRE ATT&CK group, technique, software. +* `OtherTags`: This comes from the `tags` field in YML detection rule which is excluded `MitreTactics` and `MitreTags`. * `RuleFile`: The filename of the detection rule that generated the alert or event. * `EvtxFile`: The evtx filename that caused the alert or event. * `RecordInformation`: All field information. @@ -525,7 +527,9 @@ Please use `--set-default-profile` option when you want to overwrite `default_p |%Channel% | `Channel` | |%Level% | `Level` | |%EventID% | `EventID` | -|%MitreAttack% | `MitreAttack` | +|%MitreTactics% | `MitreTactics` | +|%MitreTags% | `MitreTags` | +|%OtherTags% | `OtherTags` | |%RecordID% | `RecordID` | |%RuleTitle% | `Title` | |%Details% | `Details` | From cd4dad0afce7a6a21a2a63c4fcf8698d9ebf22f1 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:38:25 +0900 Subject: [PATCH 09/16] updated rules --- rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules b/rules index cf1ea8fd..aa0a16b1 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit cf1ea8fd0dd1ed3d09ac2961980350635911e53c +Subproject commit aa0a16b1d5f56cb6e08d6af8eeea64a660148172 From bbd6c98616d54095ca5163d2b6e4960e2bc7ba3a Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 00:56:47 +0900 Subject: [PATCH 10/16] fixed profile reference wrong file ref --- src/detections/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detections/message.rs b/src/detections/message.rs index 214d0e8a..a737306e 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -67,7 +67,7 @@ lazy_static! { pub static ref PIVOT_KEYWORD_LIST_FLAG: bool = configs::CONFIG.read().unwrap().args.pivot_keywords_list; pub static ref DEFAULT_DETAILS: HashMap = get_default_details(&format!( - "{}/default_details.txt", + "{}/default_details.yaml", configs::CONFIG .read() .unwrap() From b07b4f6fb28eb6c5baf6bbb669944144707d12d4 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 7 Aug 2022 01:02:18 +0900 Subject: [PATCH 11/16] Revert "fixed profile reference wrong file ref" This reverts commit bbd6c98616d54095ca5163d2b6e4960e2bc7ba3a. --- src/detections/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detections/message.rs b/src/detections/message.rs index a737306e..214d0e8a 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -67,7 +67,7 @@ lazy_static! { pub static ref PIVOT_KEYWORD_LIST_FLAG: bool = configs::CONFIG.read().unwrap().args.pivot_keywords_list; pub static ref DEFAULT_DETAILS: HashMap = get_default_details(&format!( - "{}/default_details.yaml", + "{}/default_details.txt", configs::CONFIG .read() .unwrap() From 187192c5d845177940c8194ba909129623c02efd Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Mon, 8 Aug 2022 03:24:22 +0900 Subject: [PATCH 12/16] To removed unnecessary all-tags option. --- src/afterfact.rs | 4 +--- src/detections/configs.rs | 4 ---- src/detections/message.rs | 23 ++--------------------- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index a3b82fad..076b57a4 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -580,9 +580,7 @@ mod tests { #[test] fn test_emit_csv_output() { let mock_ch_filter = message::create_output_filter_config( - "rules/config/channel_abbreviations.txt", - true, - false, + "test_files/config/channel_abbreviations.txt", ); let test_filepath: &str = "test.evtx"; let test_rulepath: &str = "test-rule.yml"; diff --git a/src/detections/configs.rs b/src/detections/configs.rs index ab343d9f..a0ac1b74 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -93,10 +93,6 @@ pub struct Config { #[clap(short = 'o', long, value_name = "CSV_TIMELINE")] pub output: Option, - /// Output all tags when saving to a CSV file - #[clap(long = "all-tags")] - pub all_tags: bool, - /// Output verbose information #[clap(short = 'v', long)] pub verbose: bool, diff --git a/src/detections/message.rs b/src/detections/message.rs index 214d0e8a..b5c9c248 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -51,8 +51,6 @@ lazy_static! { utils::check_setting_path(&CURRENT_EXE_PATH.to_path_buf(), "config/mitre_tactics.txt") .to_str() .unwrap(), - true, - configs::CONFIG.read().unwrap().args.all_tags ); pub static ref CH_CONFIG: HashMap = create_output_filter_config( utils::check_setting_path( @@ -61,8 +59,6 @@ lazy_static! { ) .to_str() .unwrap(), - false, - configs::CONFIG.read().unwrap().args.all_tags ); pub static ref PIVOT_KEYWORD_LIST_FLAG: bool = configs::CONFIG.read().unwrap().args.pivot_keywords_list; @@ -96,13 +92,8 @@ lazy_static! { /// ex. attack.impact,Impact pub fn create_output_filter_config( path: &str, - read_tags: bool, - pass_flag: bool, ) -> HashMap { let mut ret: HashMap = HashMap::new(); - if read_tags && pass_flag { - return ret; - } let read_result = utils::read_csv(path); if read_result.is_err() { AlertMessage::alert(read_result.as_ref().unwrap_err()).ok(); @@ -594,7 +585,7 @@ mod tests { /// test of loading output filter config by mitre_tactics.txt fn test_load_mitre_tactics_log() { let actual = - create_output_filter_config("test_files/config/mitre_tactics.txt", true, false); + create_output_filter_config("test_files/config/mitre_tactics.txt"); let expected: HashMap = HashMap::from([ ("attack.impact".to_string(), "Impact".to_string()), ("xxx".to_string(), "yyy".to_string()), @@ -602,23 +593,13 @@ mod tests { _check_hashmap_element(&expected, actual); } - #[test] - /// test of loading pass by mitre_tactics.txt - fn test_no_load_output_tag() { - let actual = create_output_filter_config("test_files/config/mitre_tactics.txt", true, true); - let expected: HashMap = HashMap::new(); - _check_hashmap_element(&expected, actual); - } - #[test] /// loading test to channel_abbrevations.txt fn test_load_abbrevations() { let actual = - create_output_filter_config("test_files/config/channel_abbreviations.txt", false, true); + create_output_filter_config("test_files/config/channel_abbreviations.txt"); let actual2 = create_output_filter_config( "test_files/config/channel_abbreviations.txt", - false, - false, ); let expected: HashMap = HashMap::from([ ("Security".to_string(), "Sec".to_string()), From 9684a11d37ea5e6579f66c2435fcba075a189fab Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Mon, 8 Aug 2022 03:30:03 +0900 Subject: [PATCH 13/16] updated readme due to removed all-tags option --- README-Japanese.md | 1 - README.md | 1 - 2 files changed, 2 deletions(-) diff --git a/README-Japanese.md b/README-Japanese.md index 5ef935fe..5ad1a294 100644 --- a/README-Japanese.md +++ b/README-Japanese.md @@ -332,7 +332,6 @@ OPTIONS: --RFC-3339 RFC 3339形式で日付と時刻を出力する (例: 2022-02-22 22:00:00.123456-06:00) --US-military-time 24時間制(ミリタリータイム)のアメリカ形式で日付と時刻を出力する (例: 02-22-2022 22:00:00.123 -06:00) --US-time アメリカ形式で日付と時刻を出力する (例: 02-22-2022 10:00:00.123 PM -06:00) - --all-tags 出力したCSVファイルにルール内のタグ情報を全て出力する -c, --rules-config ルールフォルダのコンフィグディレクトリ (デフォルト: ./rules/config) --contributors コントリビュータの一覧表示 -d, --directory .evtxファイルを持つディレクトリのパス diff --git a/README.md b/README.md index 2fa3e624..9928086c 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,6 @@ OPTIONS: --RFC-3339 Output timestamp in RFC 3339 format (ex: 2022-02-22 22:00:00.123456-06:00) --US-military-time Output timestamp in US military time format (ex: 02-22-2022 22:00:00.123 -06:00) --US-time Output timestamp in US time format (ex: 02-22-2022 10:00:00.123 PM -06:00) - --all-tags Output all tags when saving to a CSV file -c, --rules-config Specify custom rule config folder (default: ./rules/config) --contributors Print the list of contributors -d, --directory Directory of multiple .evtx files From 7cc0217cb10455d8eb8070866c6214801f7f8cf4 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Mon, 8 Aug 2022 10:09:37 +0900 Subject: [PATCH 14/16] cargo fmt --- src/afterfact.rs | 5 ++--- src/detections/detection.rs | 6 ++---- src/detections/message.rs | 14 ++++---------- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index 076b57a4..6752faa1 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -579,9 +579,8 @@ mod tests { #[test] fn test_emit_csv_output() { - let mock_ch_filter = message::create_output_filter_config( - "test_files/config/channel_abbreviations.txt", - ); + let mock_ch_filter = + message::create_output_filter_config("test_files/config/channel_abbreviations.txt"); let test_filepath: &str = "test.evtx"; let test_rulepath: &str = "test-rule.yml"; let test_title = "test_title"; diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 37772e35..258ab4b4 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -339,8 +339,7 @@ impl Detection { make_ascii_titlecase(&mut replaced_tag) }) .collect(); - profile_converter - .insert("%MitreTags%".to_string(), techniques.join(" : ")); + profile_converter.insert("%MitreTags%".to_string(), techniques.join(" : ")); } "%OtherTags%" => { let tags: &Vec = &tag_info @@ -471,8 +470,7 @@ impl Detection { make_ascii_titlecase(&mut replaced_tag) }) .collect(); - profile_converter - .insert("%MitreTags%".to_string(), techniques.join(" : ")); + profile_converter.insert("%MitreTags%".to_string(), techniques.join(" : ")); } "%OtherTags%" => { let tags: &Vec = &tag_info diff --git a/src/detections/message.rs b/src/detections/message.rs index b5c9c248..63940876 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -90,9 +90,7 @@ lazy_static! { /// ファイルパスで記載されたtagでのフル名、表示の際に置き換えられる文字列のHashMapを作成する関数。 /// ex. attack.impact,Impact -pub fn create_output_filter_config( - path: &str, -) -> HashMap { +pub fn create_output_filter_config(path: &str) -> HashMap { let mut ret: HashMap = HashMap::new(); let read_result = utils::read_csv(path); if read_result.is_err() { @@ -584,8 +582,7 @@ mod tests { #[test] /// test of loading output filter config by mitre_tactics.txt fn test_load_mitre_tactics_log() { - let actual = - create_output_filter_config("test_files/config/mitre_tactics.txt"); + let actual = create_output_filter_config("test_files/config/mitre_tactics.txt"); let expected: HashMap = HashMap::from([ ("attack.impact".to_string(), "Impact".to_string()), ("xxx".to_string(), "yyy".to_string()), @@ -596,11 +593,8 @@ mod tests { #[test] /// loading test to channel_abbrevations.txt fn test_load_abbrevations() { - let actual = - create_output_filter_config("test_files/config/channel_abbreviations.txt"); - let actual2 = create_output_filter_config( - "test_files/config/channel_abbreviations.txt", - ); + let actual = create_output_filter_config("test_files/config/channel_abbreviations.txt"); + let actual2 = create_output_filter_config("test_files/config/channel_abbreviations.txt"); let expected: HashMap = HashMap::from([ ("Security".to_string(), "Sec".to_string()), ("xxx".to_string(), "yyy".to_string()), From 216d821d286efd4e5a2eaf6b4ae713cfeb65ce3a Mon Sep 17 00:00:00 2001 From: Tanaka Zakku <71482215+YamatoSecurity@users.noreply.github.com> Date: Mon, 8 Aug 2022 10:28:08 +0900 Subject: [PATCH 15/16] update profiles --- config/default_profile.yaml | 11 +++-------- config/profiles.yaml | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/config/default_profile.yaml b/config/default_profile.yaml index f8fc4100..394b6546 100644 --- a/config/default_profile.yaml +++ b/config/default_profile.yaml @@ -2,14 +2,9 @@ Timestamp: "%Timestamp%" Computer: "%Computer%" Channel: "%Channel%" -Level: "%Level%" EventID: "%EventID%" -MitreAttack: "%MitreTactics%" -MitreTags: "%MitreTags%" -OtherTags: "%OtherTags%" +Level: "%Level%" +MitreTactics: "%MitreTactics%" RecordID: "%RecordID%" RuleTitle: "%RuleTitle%" -Details: "%Details%" -RecordInformation: "%RecordInformation%" -RuleFile: "%RuleFile%" -EvtxFile: "%EvtxFile%" \ No newline at end of file +Details: "%Details%" \ No newline at end of file diff --git a/config/profiles.yaml b/config/profiles.yaml index 78348ee2..26bcfa34 100644 --- a/config/profiles.yaml +++ b/config/profiles.yaml @@ -1,3 +1,4 @@ +#Standard profile minus MITRE ATT&CK Tactics and Record ID. minimal: Timestamp: "%Timestamp%" Computer: "%Computer%" @@ -13,32 +14,40 @@ standard: Channel: "%Channel%" EventID: "%EventID%" Level: "%Level%" - Tags: "%MitreAttack%" + MitreTactics: "%MitreTactics%" RecordID: "%RecordID%" RuleTitle: "%RuleTitle%" Details: "%Details%" -verbose-1: +#Standard profile plus MitreTags(MITRE techniques, software and groups), rule filename and EVTX filename. +verbose: Timestamp: "%Timestamp%" Computer: "%Computer%" Channel: "%Channel%" EventID: "%EventID%" Level: "%Level%" - Tags: "%MitreAttack%" + MitreTactics: "%MitreTactics%" + MitreTags: "%MitreTags%" + OtherTags: "%OtherTags%" RecordID: "%RecordID%" RuleTitle: "%RuleTitle%" Details: "%Details%" RuleFile: "%RuleFile%" EvtxFile: "%EvtxFile%" -verbose-2: +#Verbose-1 profile plus all field information. (Warning: this will more than double the output file size!) +verbose-all-field-info: Timestamp: "%Timestamp%" Computer: "%Computer%" Channel: "%Channel%" EventID: "%EventID%" Level: "%Level%" - Tags: "%MitreAttack%" + MitreTactics: "%MitreTactics%" + MitreTags: "%MitreTags%" + OtherTags: "%OtherTags%" RecordID: "%RecordID%" RuleTitle: "%RuleTitle%" Details: "%Details%" + RuleFile: "%RuleFile%" + EvtxFile: "%EvtxFile%" AllFieldInfo: "%RecordInformation%" \ No newline at end of file From 44114576639c9ce0750af07cc45bfb092bf0879a Mon Sep 17 00:00:00 2001 From: Tanaka Zakku <71482215+YamatoSecurity@users.noreply.github.com> Date: Mon, 8 Aug 2022 10:45:01 +0900 Subject: [PATCH 16/16] update profile --- config/profiles.yaml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/config/profiles.yaml b/config/profiles.yaml index 26bcfa34..d3515c29 100644 --- a/config/profiles.yaml +++ b/config/profiles.yaml @@ -35,8 +35,24 @@ verbose: RuleFile: "%RuleFile%" EvtxFile: "%EvtxFile%" -#Verbose-1 profile plus all field information. (Warning: this will more than double the output file size!) +#Verbose profile with all field information instead of the minimal fields defined in Details. verbose-all-field-info: + Timestamp: "%Timestamp%" + Computer: "%Computer%" + Channel: "%Channel%" + EventID: "%EventID%" + Level: "%Level%" + MitreTactics: "%MitreTactics%" + MitreTags: "%MitreTags%" + OtherTags: "%OtherTags%" + RecordID: "%RecordID%" + RuleTitle: "%RuleTitle%" + AllFieldInfo: "%RecordInformation%" + RuleFile: "%RuleFile%" + EvtxFile: "%EvtxFile%" + +#Verbose profile plus all field information. (Warning: this will more than double the output file size!) +verbose-details-and-all-field-info: Timestamp: "%Timestamp%" Computer: "%Computer%" Channel: "%Channel%"