From 341a5e4f86e27fc7cc09567c253e905409f63f35 Mon Sep 17 00:00:00 2001 From: kazuminn Date: Tue, 30 Nov 2021 22:54:36 +0900 Subject: [PATCH 01/12] feature fillter no use rules --- config/exclude-rules.txt | 0 config/noisy-rules.txt | 0 src/detections/configs.rs | 1 + src/detections/detection.rs | 10 ++++-- src/fillter.rs | 6 ++++ src/lib.rs | 1 + src/main.rs | 22 ++++++++++++ src/yaml.rs | 67 +++++++++++++++++++++++++++++++------ 8 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 config/exclude-rules.txt create mode 100644 config/noisy-rules.txt create mode 100644 src/fillter.rs diff --git a/config/exclude-rules.txt b/config/exclude-rules.txt new file mode 100644 index 00000000..e69de29b diff --git a/config/noisy-rules.txt b/config/noisy-rules.txt new file mode 100644 index 00000000..e69de29b diff --git a/src/detections/configs.rs b/src/detections/configs.rs index 02499876..ce158ba2 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -58,6 +58,7 @@ fn build_app<'a>() -> ArgMatches<'a> { -u --utc 'Output time in UTC format (default: local time)' -d --directory=[DIRECTORY] 'Directory of multiple .evtx files' -s --statistics 'Prints statistics of event IDs' + -n --show-noisyalerts 'do not exclude noisy rules' -t --threadnum=[NUM] 'Thread number (default: optimal number for performance)' --contributors 'Prints the list of contributors'"; App::new(&program) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index b6233769..7e610c42 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -11,6 +11,7 @@ use crate::detections::print::MESSAGES; use crate::detections::rule; use crate::detections::rule::RuleNode; use crate::detections::utils::get_serde_number_to_string; +use crate::fillter::RuleFill; use crate::yaml::ParseYaml; use std::sync::Arc; @@ -51,10 +52,15 @@ impl Detection { } // ルールファイルをパースします。 - pub fn parse_rule_files(level: String, rulespath: Option<&str>) -> Vec { + pub fn parse_rule_files( + level: String, + rulespath: Option<&str>, + fill_ids: RuleFill, + ) -> Vec { // ルールファイルのパースを実行 let mut rulefile_loader = ParseYaml::new(); - let result_readdir = rulefile_loader.read_dir(rulespath.unwrap_or(DIRPATH_RULES), &level); + let result_readdir = + rulefile_loader.read_dir(rulespath.unwrap_or(DIRPATH_RULES), &level, fill_ids); if result_readdir.is_err() { AlertMessage::alert( &mut std::io::stderr().lock(), diff --git a/src/fillter.rs b/src/fillter.rs new file mode 100644 index 00000000..0cd68b2a --- /dev/null +++ b/src/fillter.rs @@ -0,0 +1,6 @@ +use std::collections::HashMap; + +#[derive(Clone, Debug)] +pub struct RuleFill { + pub no_use_rule: HashMap, +} diff --git a/src/lib.rs b/src/lib.rs index 044dac24..9bf20692 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ pub mod afterfact; pub mod detections; +pub mod fillter; pub mod notify; pub mod omikuji; pub mod timeline; diff --git a/src/main.rs b/src/main.rs index 6b6b34c0..12d4c8a8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,10 +6,12 @@ use evtx::{EvtxParser, ParserSettings}; use hayabusa::detections::detection; use hayabusa::detections::detection::EvtxRecordInfo; use hayabusa::detections::print::AlertMessage; +use hayabusa::fillter; use hayabusa::omikuji::Omikuji; use hayabusa::{afterfact::after_fact, detections::utils}; use hayabusa::{detections::configs, timeline::timeline::Timeline}; use hhmmss::Hhmmss; +use std::collections::HashMap; use std::{ fs::{self, File}, path::PathBuf, @@ -119,9 +121,29 @@ fn analysis_files(evtx_files: Vec) { .unwrap_or("INFO") .to_uppercase(); println!("Analyzing event files: {:?}", evtx_files.len()); + + //除外ルール前処理 + let mut ids = String::from_utf8(fs::read("config/exclude-rules.txt").unwrap()).unwrap(); + if !configs::CONFIG + .read() + .unwrap() + .args + .is_present("show-noisyalerts") + { + ids += &String::from_utf8(fs::read("config/noisy-rules.txt").unwrap()).unwrap(); + } + + let mut fill_ids = fillter::RuleFill { + no_use_rule: HashMap::new(), + }; + + for v in ids.split_whitespace().next() { + fill_ids.no_use_rule.insert(v.to_string(), true); + } let rule_files = detection::Detection::parse_rule_files( level, configs::CONFIG.read().unwrap().args.value_of("rules"), + fill_ids, ); let mut detection = detection::Detection::new(rule_files); for evtx_file in evtx_files { diff --git a/src/yaml.rs b/src/yaml.rs index b0ef5065..e67ac40b 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -3,6 +3,7 @@ extern crate yaml_rust; use crate::detections::configs; use crate::detections::print::AlertMessage; +use crate::fillter::RuleFill; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; @@ -42,13 +43,18 @@ impl ParseYaml { Ok(file_content) } - pub fn read_dir>(&mut self, path: P, level: &str) -> io::Result { + pub fn read_dir>( + &mut self, + path: P, + level: &str, + fill_ids: RuleFill, + ) -> io::Result { let mut entries = fs::read_dir(path)?; let yaml_docs = entries.try_fold(vec![], |mut ret, entry| { let entry = entry?; // フォルダは再帰的に呼び出す。 if entry.file_type()?.is_dir() { - self.read_dir(entry.path(), level)?; + self.read_dir(entry.path(), level, fill_ids.clone())?; return io::Result::Ok(ret); } // ファイル以外は無視 @@ -115,6 +121,7 @@ impl ParseYaml { .unwrap_or(&0) + 1, ); + if configs::CONFIG.read().unwrap().args.is_present("verbose") { println!("Loaded yml file path: {}", filepath); } @@ -130,6 +137,18 @@ impl ParseYaml { return Option::None; } + //除外されたルールは無視する + match fill_ids + .no_use_rule + .get(&yaml_doc["id"].as_str().unwrap().to_string()) + { + Some(_) => (), + None => { + self.ignorerule_count += 1; + return Option::None; + } + } + return Option::Some((filepath, yaml_doc)); }) .collect(); @@ -148,7 +167,14 @@ mod tests { #[test] fn test_read_dir_yaml() { let mut yaml = yaml::ParseYaml::new(); - &yaml.read_dir("test_files/rules/yaml/".to_string(), &"".to_owned()); + let mut fill_ids = fillter::RuleFill { + no_use_rule: HashMap::new(), + }; + &yaml.read_dir( + "test_files/rules/yaml/".to_string(), + &"".to_owned(), + fill_ids, + ); assert_ne!(yaml.files.len(), 0); } @@ -183,7 +209,10 @@ mod tests { fn test_default_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - yaml.read_dir(path.to_path_buf(), &"").unwrap(); + let mut fill_ids = RuleFill { + no_use_rule: HashMap::new(), + }; + yaml.read_dir(path.to_path_buf(), &"", fill_ids).unwrap(); assert_eq!(yaml.files.len(), 4); } @@ -191,36 +220,54 @@ mod tests { fn test_info_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - yaml.read_dir(path.to_path_buf(), &"INFO").unwrap(); + let mut fill_ids = RuleFill { + no_use_rule: HashMap::new(), + }; + yaml.read_dir(path.to_path_buf(), &"INFO", fill_ids) + .unwrap(); assert_eq!(yaml.files.len(), 5); } #[test] fn test_low_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - - yaml.read_dir(path.to_path_buf(), &"LOW").unwrap(); + let mut fill_ids = RuleFill { + no_use_rule: HashMap::new(), + }; + yaml.read_dir(path.to_path_buf(), &"LOW", fill_ids).unwrap(); assert_eq!(yaml.files.len(), 4); } #[test] fn test_medium_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - yaml.read_dir(path.to_path_buf(), &"MEDIUM").unwrap(); + let mut fill_ids = RuleFill { + no_use_rule: HashMap::new(), + }; + yaml.read_dir(path.to_path_buf(), &"MEDIUM", fill_ids) + .unwrap(); assert_eq!(yaml.files.len(), 3); } #[test] fn test_high_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - yaml.read_dir(path.to_path_buf(), &"HIGH").unwrap(); + let mut fill_ids = RuleFill { + no_use_rule: HashMap::new(), + }; + yaml.read_dir(path.to_path_buf(), &"HIGH", fill_ids) + .unwrap(); assert_eq!(yaml.files.len(), 2); } #[test] fn test_critical_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - yaml.read_dir(path.to_path_buf(), &"CRITICAL").unwrap(); + let mut fill_ids = RuleFill { + no_use_rule: HashMap::new(), + }; + yaml.read_dir(path.to_path_buf(), &"CRITICAL", fill_ids) + .unwrap(); assert_eq!(yaml.files.len(), 1); } } From 838a935d34e11bce146cfe8e2054a2998a9168f3 Mon Sep 17 00:00:00 2001 From: kazuminn Date: Thu, 2 Dec 2021 00:33:19 +0900 Subject: [PATCH 02/12] pass test --- src/detections/detection.rs | 5 ++++- src/main.rs | 2 +- src/yaml.rs | 34 ++++++++++++++++++---------------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 7e610c42..97ab8a9b 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -266,6 +266,9 @@ impl Detection { fn test_parse_rule_files() { let level = "INFO"; let opt_rule_path = Some("./test_files/rules/level_yaml"); - let cole = Detection::parse_rule_files(level.to_owned(), opt_rule_path); + let fill_ids = RuleFill { + no_use_rule: HashMap::from([("".to_string(), true)]), + }; + let cole = Detection::parse_rule_files(level.to_owned(), opt_rule_path, fill_ids); assert_eq!(5, cole.len()); } diff --git a/src/main.rs b/src/main.rs index 12d4c8a8..075d116e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -134,7 +134,7 @@ fn analysis_files(evtx_files: Vec) { } let mut fill_ids = fillter::RuleFill { - no_use_rule: HashMap::new(), + no_use_rule: HashMap::from([("".to_string(), true)]), }; for v in ids.split_whitespace().next() { diff --git a/src/yaml.rs b/src/yaml.rs index e67ac40b..9d5ece71 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -140,7 +140,7 @@ impl ParseYaml { //除外されたルールは無視する match fill_ids .no_use_rule - .get(&yaml_doc["id"].as_str().unwrap().to_string()) + .get(&yaml_doc["id"].as_str().unwrap_or("").to_string()) { Some(_) => (), None => { @@ -161,16 +161,18 @@ impl ParseYaml { mod tests { use crate::yaml; + use crate::yaml::RuleFill; + use std::collections::HashMap; use std::path::Path; use yaml_rust::YamlLoader; #[test] fn test_read_dir_yaml() { let mut yaml = yaml::ParseYaml::new(); - let mut fill_ids = fillter::RuleFill { - no_use_rule: HashMap::new(), + let fill_ids = RuleFill { + no_use_rule: HashMap::from([("".to_string(), true)]), }; - &yaml.read_dir( + let _ = &yaml.read_dir( "test_files/rules/yaml/".to_string(), &"".to_owned(), fill_ids, @@ -209,8 +211,8 @@ mod tests { fn test_default_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let mut fill_ids = RuleFill { - no_use_rule: HashMap::new(), + let fill_ids = RuleFill { + no_use_rule: HashMap::from([("".to_string(), true)]), }; yaml.read_dir(path.to_path_buf(), &"", fill_ids).unwrap(); assert_eq!(yaml.files.len(), 4); @@ -220,8 +222,8 @@ mod tests { fn test_info_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let mut fill_ids = RuleFill { - no_use_rule: HashMap::new(), + let fill_ids = RuleFill { + no_use_rule: HashMap::from([("".to_string(), true)]), }; yaml.read_dir(path.to_path_buf(), &"INFO", fill_ids) .unwrap(); @@ -231,8 +233,8 @@ mod tests { fn test_low_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let mut fill_ids = RuleFill { - no_use_rule: HashMap::new(), + let fill_ids = RuleFill { + no_use_rule: HashMap::from([("".to_string(), true)]), }; yaml.read_dir(path.to_path_buf(), &"LOW", fill_ids).unwrap(); assert_eq!(yaml.files.len(), 4); @@ -241,8 +243,8 @@ mod tests { fn test_medium_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let mut fill_ids = RuleFill { - no_use_rule: HashMap::new(), + let fill_ids = RuleFill { + no_use_rule: HashMap::from([("".to_string(), true)]), }; yaml.read_dir(path.to_path_buf(), &"MEDIUM", fill_ids) .unwrap(); @@ -252,8 +254,8 @@ mod tests { fn test_high_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let mut fill_ids = RuleFill { - no_use_rule: HashMap::new(), + let fill_ids = RuleFill { + no_use_rule: HashMap::from([("".to_string(), true)]), }; yaml.read_dir(path.to_path_buf(), &"HIGH", fill_ids) .unwrap(); @@ -263,8 +265,8 @@ mod tests { fn test_critical_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let mut fill_ids = RuleFill { - no_use_rule: HashMap::new(), + let fill_ids = RuleFill { + no_use_rule: HashMap::from([("".to_string(), true)]), }; yaml.read_dir(path.to_path_buf(), &"CRITICAL", fill_ids) .unwrap(); From b9c415eab5b45a25d53b0389b60a17c0dd24e64a Mon Sep 17 00:00:00 2001 From: kazuminn Date: Thu, 2 Dec 2021 00:43:31 +0900 Subject: [PATCH 03/12] add --- src/yaml.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yaml.rs b/src/yaml.rs index 9d5ece71..ecb241d3 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -225,7 +225,7 @@ mod tests { let fill_ids = RuleFill { no_use_rule: HashMap::from([("".to_string(), true)]), }; - yaml.read_dir(path.to_path_buf(), &"INFO", fill_ids) + yaml.read_dir(path.to_path_buf(), &"informational", fill_ids) .unwrap(); assert_eq!(yaml.files.len(), 5); } From c961c3768c506c5611e7c63914d8add0ec3fbac3 Mon Sep 17 00:00:00 2001 From: ichiichi11 Date: Sat, 4 Dec 2021 18:46:11 +0900 Subject: [PATCH 04/12] change from hashmap to hashset and remove unnecessary copy. --- src/detections/detection.rs | 6 +++--- src/fillter.rs | 6 ++++-- src/main.rs | 8 ++++---- src/yaml.rs | 34 +++++++++++++++++----------------- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index b6e3afd0..d615c4ea 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -55,7 +55,7 @@ impl Detection { pub fn parse_rule_files( level: String, rulespath: Option<&str>, - fill_ids: RuleFill, + fill_ids: &RuleFill, ) -> Vec { // ルールファイルのパースを実行 let mut rulefile_loader = ParseYaml::new(); @@ -274,8 +274,8 @@ fn test_parse_rule_files() { let level = "informational"; let opt_rule_path = Some("./test_files/rules/level_yaml"); let fill_ids = RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: std::collections::HashSet::new(), }; - let cole = Detection::parse_rule_files(level.to_owned(), opt_rule_path, fill_ids); + let cole = Detection::parse_rule_files(level.to_owned(), opt_rule_path, &fill_ids); assert_eq!(5, cole.len()); } diff --git a/src/fillter.rs b/src/fillter.rs index 0cd68b2a..058bd0fc 100644 --- a/src/fillter.rs +++ b/src/fillter.rs @@ -1,6 +1,8 @@ -use std::collections::HashMap; +use std::collections::HashSet; + + #[derive(Clone, Debug)] pub struct RuleFill { - pub no_use_rule: HashMap, + pub no_use_rule: HashSet, } diff --git a/src/main.rs b/src/main.rs index 8ad991af..6c257089 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use hayabusa::{afterfact::after_fact, detections::utils}; use hayabusa::{detections::configs, timeline::timeline::Timeline}; use hhmmss::Hhmmss; use serde_json::Value; -use std::collections::HashMap; +use std::collections::HashSet; use std::{ fs::{self, File}, path::PathBuf, @@ -135,16 +135,16 @@ fn analysis_files(evtx_files: Vec) { } let mut fill_ids = fillter::RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: HashSet::new(), }; for v in ids.split_whitespace().next() { - fill_ids.no_use_rule.insert(v.to_string(), true); + fill_ids.no_use_rule.insert(v.to_string()); } let rule_files = detection::Detection::parse_rule_files( level, configs::CONFIG.read().unwrap().args.value_of("rules"), - fill_ids, + &fill_ids, ); let mut detection = detection::Detection::new(rule_files); for evtx_file in evtx_files { diff --git a/src/yaml.rs b/src/yaml.rs index c32d6950..98fccf0a 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -47,14 +47,14 @@ impl ParseYaml { &mut self, path: P, level: &str, - fill_ids: RuleFill, + fill_ids: &RuleFill, ) -> io::Result { let mut entries = fs::read_dir(path)?; let yaml_docs = entries.try_fold(vec![], |mut ret, entry| { let entry = entry?; // フォルダは再帰的に呼び出す。 if entry.file_type()?.is_dir() { - self.read_dir(entry.path(), level, fill_ids.clone())?; + self.read_dir(entry.path(), level, fill_ids)?; return io::Result::Ok(ret); } // ファイル以外は無視 @@ -162,7 +162,7 @@ mod tests { use crate::yaml; use crate::yaml::RuleFill; - use std::collections::HashMap; + use std::collections::HashSet; use std::path::Path; use yaml_rust::YamlLoader; @@ -170,12 +170,12 @@ mod tests { fn test_read_dir_yaml() { let mut yaml = yaml::ParseYaml::new(); let fill_ids = RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: HashSet::new(), }; let _ = &yaml.read_dir( "test_files/rules/yaml/".to_string(), &"".to_owned(), - fill_ids, + &fill_ids, ); assert_ne!(yaml.files.len(), 0); } @@ -212,9 +212,9 @@ mod tests { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); let fill_ids = RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: HashSet::new(), }; - yaml.read_dir(path.to_path_buf(), &"", fill_ids).unwrap(); + yaml.read_dir(path.to_path_buf(), &"", &fill_ids).unwrap(); assert_eq!(yaml.files.len(), 5); } @@ -223,9 +223,9 @@ mod tests { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); let fill_ids = RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: HashSet::new(), }; - yaml.read_dir(path.to_path_buf(), &"informational", fill_ids) + yaml.read_dir(path.to_path_buf(), &"informational", &fill_ids) .unwrap(); assert_eq!(yaml.files.len(), 5); } @@ -234,9 +234,9 @@ mod tests { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); let fill_ids = RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: HashSet::new(), }; - yaml.read_dir(path.to_path_buf(), &"LOW", fill_ids).unwrap(); + yaml.read_dir(path.to_path_buf(), &"LOW", &fill_ids).unwrap(); assert_eq!(yaml.files.len(), 4); } #[test] @@ -244,9 +244,9 @@ mod tests { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); let fill_ids = RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: HashSet::new(), }; - yaml.read_dir(path.to_path_buf(), &"MEDIUM", fill_ids) + yaml.read_dir(path.to_path_buf(), &"MEDIUM", &fill_ids) .unwrap(); assert_eq!(yaml.files.len(), 3); } @@ -255,9 +255,9 @@ mod tests { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); let fill_ids = RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: HashSet::new(), }; - yaml.read_dir(path.to_path_buf(), &"HIGH", fill_ids) + yaml.read_dir(path.to_path_buf(), &"HIGH", &fill_ids) .unwrap(); assert_eq!(yaml.files.len(), 2); } @@ -266,9 +266,9 @@ mod tests { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); let fill_ids = RuleFill { - no_use_rule: HashMap::from([("".to_string(), true)]), + no_use_rule: HashSet::new(), }; - yaml.read_dir(path.to_path_buf(), &"CRITICAL", fill_ids) + yaml.read_dir(path.to_path_buf(), &"CRITICAL", &fill_ids) .unwrap(); assert_eq!(yaml.files.len(), 1); } From 916921455349f0ff6232acc49360dec1275004c5 Mon Sep 17 00:00:00 2001 From: ichiichi11 Date: Sat, 4 Dec 2021 19:09:41 +0900 Subject: [PATCH 05/12] fix bug. --- src/main.rs | 3 ++- src/yaml.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6c257089..15255e6e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -131,6 +131,7 @@ fn analysis_files(evtx_files: Vec) { .args .is_present("show-noisyalerts") { + ids += "\n"; // 改行を入れないとexclude-rulesの一番最後の行とnoisy-rules.txtの一番最後の行が一行にまとめられてしまう。 ids += &String::from_utf8(fs::read("config/noisy-rules.txt").unwrap()).unwrap(); } @@ -138,7 +139,7 @@ fn analysis_files(evtx_files: Vec) { no_use_rule: HashSet::new(), }; - for v in ids.split_whitespace().next() { + for v in ids.split_whitespace() { fill_ids.no_use_rule.insert(v.to_string()); } let rule_files = detection::Detection::parse_rule_files( diff --git a/src/yaml.rs b/src/yaml.rs index 98fccf0a..8c89ec01 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -142,8 +142,8 @@ impl ParseYaml { .no_use_rule .get(&yaml_doc["id"].as_str().unwrap_or("").to_string()) { - Some(_) => (), - None => { + None => (), + Some(_) => { self.ignorerule_count += 1; return Option::None; } From 191d1df9f05512cbb6fd0234187f93bb3df03705 Mon Sep 17 00:00:00 2001 From: ichiichi11 Date: Sat, 4 Dec 2021 19:23:50 +0900 Subject: [PATCH 06/12] add exclude files and fix bugs. --- config/exclude-rules.txt | 2 ++ src/fillter.rs | 2 -- src/main.rs | 9 +++++++-- src/yaml.rs | 19 ++++++++++--------- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/config/exclude-rules.txt b/config/exclude-rules.txt index e69de29b..69422602 100644 --- a/config/exclude-rules.txt +++ b/config/exclude-rules.txt @@ -0,0 +1,2 @@ +4fe151c2-ecf9-4fae-95ae-b88ec9c2fca6 +c92f1896-d1d2-43c3-92d5-7a5b35c217bb \ No newline at end of file diff --git a/src/fillter.rs b/src/fillter.rs index 058bd0fc..d3ddb429 100644 --- a/src/fillter.rs +++ b/src/fillter.rs @@ -1,7 +1,5 @@ use std::collections::HashSet; - - #[derive(Clone, Debug)] pub struct RuleFill { pub no_use_rule: HashSet, diff --git a/src/main.rs b/src/main.rs index 15255e6e..86050cbd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -131,7 +131,7 @@ fn analysis_files(evtx_files: Vec) { .args .is_present("show-noisyalerts") { - ids += "\n"; // 改行を入れないとexclude-rulesの一番最後の行とnoisy-rules.txtの一番最後の行が一行にまとめられてしまう。 + ids += "\n"; // 改行を入れないとexclude-rulesの一番最後の行とnoisy-rules.txtの一番最後の行が一行にまとめられてしまう。 ids += &String::from_utf8(fs::read("config/noisy-rules.txt").unwrap()).unwrap(); } @@ -140,7 +140,12 @@ fn analysis_files(evtx_files: Vec) { }; for v in ids.split_whitespace() { - fill_ids.no_use_rule.insert(v.to_string()); + let v = v.to_string(); + if v.is_empty() { + // 空行は無視する。 + continue; + } + fill_ids.no_use_rule.insert(v); } let rule_files = detection::Detection::parse_rule_files( level, diff --git a/src/yaml.rs b/src/yaml.rs index 8c89ec01..da18486c 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -138,14 +138,14 @@ impl ParseYaml { } //除外されたルールは無視する - match fill_ids - .no_use_rule - .get(&yaml_doc["id"].as_str().unwrap_or("").to_string()) - { - None => (), - Some(_) => { - self.ignorerule_count += 1; - return Option::None; + let rule_id = &yaml_doc["id"].as_str(); + if rule_id.is_some() { + match fill_ids.no_use_rule.get(&rule_id.unwrap_or("").to_string()) { + None => (), + Some(_) => { + self.ignorerule_count += 1; + return Option::None; + } } } @@ -236,7 +236,8 @@ mod tests { let fill_ids = RuleFill { no_use_rule: HashSet::new(), }; - yaml.read_dir(path.to_path_buf(), &"LOW", &fill_ids).unwrap(); + yaml.read_dir(path.to_path_buf(), &"LOW", &fill_ids) + .unwrap(); assert_eq!(yaml.files.len(), 4); } #[test] From c8473b766887bce8ac6cdfb8ed9e06521870ed79 Mon Sep 17 00:00:00 2001 From: kazuminn Date: Wed, 8 Dec 2021 23:16:46 +0900 Subject: [PATCH 07/12] remove comment --- config/noisy-rules.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/noisy-rules.txt b/config/noisy-rules.txt index 6e03bcf7..f25d1a33 100644 --- a/config/noisy-rules.txt +++ b/config/noisy-rules.txt @@ -1,5 +1,5 @@ -0f06a3a5-6a09-413f-8743-e6cf35561297 # sysmon_wmi_event_subscription.yml -b0d77106-7bb0-41fe-bd94-d1752164d066 # win_rare_schtasks_creations.yml -66bfef30-22a5-4fcd-ad44-8d81e60922ae # win_rare_service_installs.yml -e98374a6-e2d9-4076-9b5c-11bdb2569995 # win_susp_failed_logons_single_source.yml -6309ffc4-8fa2-47cf-96b8-a2f72e58e538 # win_susp_failed_logons_single_source2.yml \ No newline at end of file +0f06a3a5-6a09-413f-8743-e6cf35561297 +b0d77106-7bb0-41fe-bd94-d1752164d066 +66bfef30-22a5-4fcd-ad44-8d81e60922ae +e98374a6-e2d9-4076-9b5c-11bdb2569995 +6309ffc4-8fa2-47cf-96b8-a2f72e58e538 \ No newline at end of file From b9831ca38a14823c2c0f7ad27103aa9a02c15222 Mon Sep 17 00:00:00 2001 From: kazuminn Date: Thu, 9 Dec 2021 00:57:40 +0900 Subject: [PATCH 08/12] add test for exclude rules --- src/detections/detection.rs | 10 ++++---- src/fillter.rs | 30 ++++++++++++++++++++++++ src/main.rs | 27 +--------------------- src/yaml.rs | 46 +++++++++++++++++-------------------- 4 files changed, 56 insertions(+), 57 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 52dab334..1904d5fe 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -11,7 +11,7 @@ use crate::detections::print::MESSAGES; use crate::detections::rule; use crate::detections::rule::RuleNode; use crate::detections::utils::get_serde_number_to_string; -use crate::fillter::RuleFill; +use crate::fillter; use crate::yaml::ParseYaml; use std::sync::Arc; @@ -55,7 +55,7 @@ impl Detection { pub fn parse_rule_files( level: String, rulespath: Option<&str>, - fill_ids: &RuleFill, + fill_ids: &fillter::RuleFill, ) -> Vec { // ルールファイルのパースを実行 let mut rulefile_loader = ParseYaml::new(); @@ -275,9 +275,7 @@ impl Detection { fn test_parse_rule_files() { let level = "informational"; let opt_rule_path = Some("./test_files/rules/level_yaml"); - let fill_ids = RuleFill { - no_use_rule: std::collections::HashSet::new(), - }; - let cole = Detection::parse_rule_files(level.to_owned(), opt_rule_path, &fill_ids); + let cole = + Detection::parse_rule_files(level.to_owned(), opt_rule_path, &fillter::exclude_ids()); assert_eq!(5, cole.len()); } diff --git a/src/fillter.rs b/src/fillter.rs index d3ddb429..7b61d175 100644 --- a/src/fillter.rs +++ b/src/fillter.rs @@ -1,6 +1,36 @@ +use crate::detections::configs; use std::collections::HashSet; +use std::fs; #[derive(Clone, Debug)] pub struct RuleFill { pub no_use_rule: HashSet, } + +pub fn exclude_ids() -> RuleFill { + let mut ids = String::from_utf8(fs::read("config/exclude-rules.txt").unwrap()).unwrap(); + if !configs::CONFIG + .read() + .unwrap() + .args + .is_present("show-noisyalerts") + { + ids += "\n"; // 改行を入れないとexclude-rulesの一番最後の行とnoisy-rules.txtの一番最後の行が一行にまとめられてしまう。 + ids += &String::from_utf8(fs::read("config/noisy-rules.txt").unwrap()).unwrap(); + } + + let mut fill_ids = RuleFill { + no_use_rule: HashSet::new(), + }; + + for v in ids.split_whitespace() { + let v = v.to_string(); + if v.is_empty() { + // 空行は無視する。 + continue; + } + fill_ids.no_use_rule.insert(v); + } + + return fill_ids; +} diff --git a/src/main.rs b/src/main.rs index f4e86cf6..525256eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,6 @@ use hayabusa::{detections::configs, timeline::timeline::Timeline}; use hhmmss::Hhmmss; use pbr::ProgressBar; use serde_json::Value; -use std::collections::HashSet; use std::{ fs::{self, File}, path::PathBuf, @@ -124,34 +123,10 @@ fn analysis_files(evtx_files: Vec) { .to_uppercase(); println!("Analyzing event files: {:?}", evtx_files.len()); - //除外ルール前処理 - let mut ids = String::from_utf8(fs::read("config/exclude-rules.txt").unwrap()).unwrap(); - if !configs::CONFIG - .read() - .unwrap() - .args - .is_present("show-noisyalerts") - { - ids += "\n"; // 改行を入れないとexclude-rulesの一番最後の行とnoisy-rules.txtの一番最後の行が一行にまとめられてしまう。 - ids += &String::from_utf8(fs::read("config/noisy-rules.txt").unwrap()).unwrap(); - } - - let mut fill_ids = fillter::RuleFill { - no_use_rule: HashSet::new(), - }; - - for v in ids.split_whitespace() { - let v = v.to_string(); - if v.is_empty() { - // 空行は無視する。 - continue; - } - fill_ids.no_use_rule.insert(v); - } let rule_files = detection::Detection::parse_rule_files( level, configs::CONFIG.read().unwrap().args.value_of("rules"), - &fill_ids, + &fillter::exclude_ids(), ); let mut pb = ProgressBar::new(evtx_files.len() as u64); let mut detection = detection::Detection::new(rule_files); diff --git a/src/yaml.rs b/src/yaml.rs index da18486c..a06aac28 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -160,6 +160,7 @@ impl ParseYaml { #[cfg(test)] mod tests { + use crate::fillter; use crate::yaml; use crate::yaml::RuleFill; use std::collections::HashSet; @@ -211,10 +212,8 @@ mod tests { fn test_default_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let fill_ids = RuleFill { - no_use_rule: HashSet::new(), - }; - yaml.read_dir(path.to_path_buf(), &"", &fill_ids).unwrap(); + yaml.read_dir(path.to_path_buf(), &"", &fillter::exclude_ids()) + .unwrap(); assert_eq!(yaml.files.len(), 5); } @@ -222,21 +221,19 @@ mod tests { fn test_info_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let fill_ids = RuleFill { - no_use_rule: HashSet::new(), - }; - yaml.read_dir(path.to_path_buf(), &"informational", &fill_ids) - .unwrap(); + yaml.read_dir( + path.to_path_buf(), + &"informational", + &fillter::exclude_ids(), + ) + .unwrap(); assert_eq!(yaml.files.len(), 5); } #[test] fn test_low_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let fill_ids = RuleFill { - no_use_rule: HashSet::new(), - }; - yaml.read_dir(path.to_path_buf(), &"LOW", &fill_ids) + yaml.read_dir(path.to_path_buf(), &"LOW", &fillter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 4); } @@ -244,10 +241,7 @@ mod tests { fn test_medium_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let fill_ids = RuleFill { - no_use_rule: HashSet::new(), - }; - yaml.read_dir(path.to_path_buf(), &"MEDIUM", &fill_ids) + yaml.read_dir(path.to_path_buf(), &"MEDIUM", &fillter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 3); } @@ -255,10 +249,7 @@ mod tests { fn test_high_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let fill_ids = RuleFill { - no_use_rule: HashSet::new(), - }; - yaml.read_dir(path.to_path_buf(), &"HIGH", &fill_ids) + yaml.read_dir(path.to_path_buf(), &"HIGH", &fillter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 2); } @@ -266,11 +257,16 @@ mod tests { fn test_critical_level_read_yaml() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/level_yaml"); - let fill_ids = RuleFill { - no_use_rule: HashSet::new(), - }; - yaml.read_dir(path.to_path_buf(), &"CRITICAL", &fill_ids) + yaml.read_dir(path.to_path_buf(), &"CRITICAL", &fillter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 1); } + #[test] + fn test_exclude_rules_file() { + let mut yaml = yaml::ParseYaml::new(); + let path = Path::new("test_files/rules/exclude_rules"); + yaml.read_dir(path.to_path_buf(), &"", &fillter::exclude_ids()) + .unwrap(); + assert_eq!(yaml.ignorerule_count, 1); + } } From 3f11e426bad4319c87d8ce060e0a52a04850eca8 Mon Sep 17 00:00:00 2001 From: kazuminn Date: Thu, 9 Dec 2021 01:06:50 +0900 Subject: [PATCH 09/12] add test rule file --- test_files/rules/exclude_rules/1.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 test_files/rules/exclude_rules/1.yml diff --git a/test_files/rules/exclude_rules/1.yml b/test_files/rules/exclude_rules/1.yml new file mode 100644 index 00000000..76e3e73d --- /dev/null +++ b/test_files/rules/exclude_rules/1.yml @@ -0,0 +1,19 @@ +title: Sysmon Check command lines +id : 4fe151c2-ecf9-4fae-95ae-b88ec9c2fca6 +description: hogehoge +enabled: true +author: Yea +logsource: + product: windows +detection: + selection: + EventLog: Sysmon + EventID: 1 + CommandLine: '*' + condition: selection +falsepositives: + - unknown +level: medium +output: 'CommandLine=%CommandLine%¥nParentImage=%ParentImage%' +creation_date: 2020/11/8 +updated_date: 2020/11/8 \ No newline at end of file From 360d80b578113a9510a88d2d437e00a91ffa62bc Mon Sep 17 00:00:00 2001 From: kazuminn Date: Thu, 9 Dec 2021 01:15:01 +0900 Subject: [PATCH 10/12] clear --- src/yaml.rs | 2 +- test_files/rules/exclude_rules/1.yml | 19 ------------------- test_files/rules/yaml/1.yml | 1 + 3 files changed, 2 insertions(+), 20 deletions(-) delete mode 100644 test_files/rules/exclude_rules/1.yml diff --git a/src/yaml.rs b/src/yaml.rs index a06aac28..e724fb6c 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -264,7 +264,7 @@ mod tests { #[test] fn test_exclude_rules_file() { let mut yaml = yaml::ParseYaml::new(); - let path = Path::new("test_files/rules/exclude_rules"); + let path = Path::new("test_files/rules/yaml"); yaml.read_dir(path.to_path_buf(), &"", &fillter::exclude_ids()) .unwrap(); assert_eq!(yaml.ignorerule_count, 1); diff --git a/test_files/rules/exclude_rules/1.yml b/test_files/rules/exclude_rules/1.yml deleted file mode 100644 index 76e3e73d..00000000 --- a/test_files/rules/exclude_rules/1.yml +++ /dev/null @@ -1,19 +0,0 @@ -title: Sysmon Check command lines -id : 4fe151c2-ecf9-4fae-95ae-b88ec9c2fca6 -description: hogehoge -enabled: true -author: Yea -logsource: - product: windows -detection: - selection: - EventLog: Sysmon - EventID: 1 - CommandLine: '*' - condition: selection -falsepositives: - - unknown -level: medium -output: 'CommandLine=%CommandLine%¥nParentImage=%ParentImage%' -creation_date: 2020/11/8 -updated_date: 2020/11/8 \ No newline at end of file diff --git a/test_files/rules/yaml/1.yml b/test_files/rules/yaml/1.yml index 5f844d26..c34d0bc2 100644 --- a/test_files/rules/yaml/1.yml +++ b/test_files/rules/yaml/1.yml @@ -1,4 +1,5 @@ title: Sysmon Check command lines +id : 4fe151c2-ecf9-4fae-95ae-b88ec9c2fca6 description: hogehoge enabled: true author: Yea From db3616b56dbaab010ce39de023b66e94858f1e6c Mon Sep 17 00:00:00 2001 From: kazuminn Date: Thu, 9 Dec 2021 01:29:23 +0900 Subject: [PATCH 11/12] add test rule files --- .../builtin/win_hidden_user_creation.yml | 1 - ...win_user_added_to_local_administrators.yml | 1 - rules/sigma/builtin/win_user_creation.yml | 1 - .../other/win_exchange_cve_2021_42321.yml | 1 - src/yaml.rs | 4 +-- test_files/rules/yaml/1.yml | 4 +-- test_files/rules/yaml/exclude1.yml | 19 +++++++++++ test_files/rules/yaml/exclude2.yml | 21 ++++++++++++ test_files/rules/yaml/exclude3.yml | 28 +++++++++++++++ test_files/rules/yaml/exclude4.yml | 30 ++++++++++++++++ test_files/rules/yaml/exclude5.yml | 31 +++++++++++++++++ test_files/rules/yaml/noisy1.yml | 25 ++++++++++++++ test_files/rules/yaml/noisy2.yml | 31 +++++++++++++++++ test_files/rules/yaml/noisy3.yml | 26 ++++++++++++++ test_files/rules/yaml/noisy4.yml | 33 ++++++++++++++++++ test_files/rules/yaml/noisy5.yml | 34 +++++++++++++++++++ 16 files changed, 281 insertions(+), 9 deletions(-) create mode 100644 test_files/rules/yaml/exclude1.yml create mode 100644 test_files/rules/yaml/exclude2.yml create mode 100644 test_files/rules/yaml/exclude3.yml create mode 100644 test_files/rules/yaml/exclude4.yml create mode 100644 test_files/rules/yaml/exclude5.yml create mode 100644 test_files/rules/yaml/noisy1.yml create mode 100644 test_files/rules/yaml/noisy2.yml create mode 100644 test_files/rules/yaml/noisy3.yml create mode 100644 test_files/rules/yaml/noisy4.yml create mode 100644 test_files/rules/yaml/noisy5.yml diff --git a/rules/sigma/builtin/win_hidden_user_creation.yml b/rules/sigma/builtin/win_hidden_user_creation.yml index 526c96dd..45f43c4a 100644 --- a/rules/sigma/builtin/win_hidden_user_creation.yml +++ b/rules/sigma/builtin/win_hidden_user_creation.yml @@ -1,4 +1,3 @@ - title: Hidden Local User Creation author: Christian Burkard date: 2021/05/03 diff --git a/rules/sigma/builtin/win_user_added_to_local_administrators.yml b/rules/sigma/builtin/win_user_added_to_local_administrators.yml index 4fe138b6..06b76c48 100644 --- a/rules/sigma/builtin/win_user_added_to_local_administrators.yml +++ b/rules/sigma/builtin/win_user_added_to_local_administrators.yml @@ -1,4 +1,3 @@ - title: User Added to Local Administrators author: Florian Roth date: 2017/03/14 diff --git a/rules/sigma/builtin/win_user_creation.yml b/rules/sigma/builtin/win_user_creation.yml index aaa45500..27ec53cc 100644 --- a/rules/sigma/builtin/win_user_creation.yml +++ b/rules/sigma/builtin/win_user_creation.yml @@ -1,4 +1,3 @@ - title: Local User Creation author: Patrick Bareiss date: 2019/04/18 diff --git a/rules/sigma/other/win_exchange_cve_2021_42321.yml b/rules/sigma/other/win_exchange_cve_2021_42321.yml index 77e2a949..e17e37cf 100644 --- a/rules/sigma/other/win_exchange_cve_2021_42321.yml +++ b/rules/sigma/other/win_exchange_cve_2021_42321.yml @@ -1,4 +1,3 @@ - title: Possible Exploitation of Exchange RCE CVE-2021-42321 author: Florian Roth, @testanull date: 2021/11/18 diff --git a/src/yaml.rs b/src/yaml.rs index e724fb6c..7420410c 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -264,9 +264,9 @@ mod tests { #[test] fn test_exclude_rules_file() { let mut yaml = yaml::ParseYaml::new(); - let path = Path::new("test_files/rules/yaml"); + let path = Path::new("test_files/rules/"); yaml.read_dir(path.to_path_buf(), &"", &fillter::exclude_ids()) .unwrap(); - assert_eq!(yaml.ignorerule_count, 1); + assert_eq!(yaml.ignorerule_count, 10); } } diff --git a/test_files/rules/yaml/1.yml b/test_files/rules/yaml/1.yml index c34d0bc2..23a32d6a 100644 --- a/test_files/rules/yaml/1.yml +++ b/test_files/rules/yaml/1.yml @@ -1,5 +1,4 @@ title: Sysmon Check command lines -id : 4fe151c2-ecf9-4fae-95ae-b88ec9c2fca6 description: hogehoge enabled: true author: Yea @@ -16,5 +15,4 @@ falsepositives: level: medium output: 'CommandLine=%CommandLine%¥nParentImage=%ParentImage%' creation_date: 2020/11/8 -updated_date: 2020/11/8 - +updated_date: 2020/11/8 \ No newline at end of file diff --git a/test_files/rules/yaml/exclude1.yml b/test_files/rules/yaml/exclude1.yml new file mode 100644 index 00000000..76e3e73d --- /dev/null +++ b/test_files/rules/yaml/exclude1.yml @@ -0,0 +1,19 @@ +title: Sysmon Check command lines +id : 4fe151c2-ecf9-4fae-95ae-b88ec9c2fca6 +description: hogehoge +enabled: true +author: Yea +logsource: + product: windows +detection: + selection: + EventLog: Sysmon + EventID: 1 + CommandLine: '*' + condition: selection +falsepositives: + - unknown +level: medium +output: 'CommandLine=%CommandLine%¥nParentImage=%ParentImage%' +creation_date: 2020/11/8 +updated_date: 2020/11/8 \ No newline at end of file diff --git a/test_files/rules/yaml/exclude2.yml b/test_files/rules/yaml/exclude2.yml new file mode 100644 index 00000000..e17e37cf --- /dev/null +++ b/test_files/rules/yaml/exclude2.yml @@ -0,0 +1,21 @@ +title: Possible Exploitation of Exchange RCE CVE-2021-42321 +author: Florian Roth, @testanull +date: 2021/11/18 +description: Detects log entries that appear in exploitation attempts against MS Exchange + RCE CVE-2021-42321 +detection: + condition: 'Cmdlet failed. Cmdlet Get-App, ' +falsepositives: +- Unknown, please report false positives via https://github.com/SigmaHQ/sigma/issues +id: c92f1896-d1d2-43c3-92d5-7a5b35c217bb +level: critical +logsource: + product: windows + service: msexchange-management +references: +- https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-42321 +status: experimental +tags: +- attack.lateral_movement +- attack.t1210 +ruletype: SIGMA diff --git a/test_files/rules/yaml/exclude3.yml b/test_files/rules/yaml/exclude3.yml new file mode 100644 index 00000000..45f43c4a --- /dev/null +++ b/test_files/rules/yaml/exclude3.yml @@ -0,0 +1,28 @@ +title: Hidden Local User Creation +author: Christian Burkard +date: 2021/05/03 +description: Detects the creation of a local hidden user account which should not + happen for event ID 4720. +detection: + SELECTION_1: + EventID: 4720 + SELECTION_2: + TargetUserName: '*$' + condition: (SELECTION_1 and SELECTION_2) +falsepositives: +- unknown +fields: +- EventCode +- AccountName +id: 7b449a5e-1db5-4dd0-a2dc-4e3a67282538 +level: high +logsource: + product: windows + service: security +references: +- https://twitter.com/SBousseaden/status/1387743867663958021 +status: experimental +tags: +- attack.persistence +- attack.t1136.001 +ruletype: SIGMA diff --git a/test_files/rules/yaml/exclude4.yml b/test_files/rules/yaml/exclude4.yml new file mode 100644 index 00000000..06b76c48 --- /dev/null +++ b/test_files/rules/yaml/exclude4.yml @@ -0,0 +1,30 @@ +title: User Added to Local Administrators +author: Florian Roth +date: 2017/03/14 +description: This rule triggers on user accounts that are added to the local Administrators + group, which could be legitimate activity or a sign of privilege escalation activity +detection: + SELECTION_1: + EventID: 4732 + SELECTION_2: + TargetUserName: Administr* + SELECTION_3: + TargetSid: S-1-5-32-544 + SELECTION_4: + SubjectUserName: '*$' + condition: ((SELECTION_1 and (SELECTION_2 or SELECTION_3)) and not (SELECTION_4)) +falsepositives: +- Legitimate administrative activity +id: c265cf08-3f99-46c1-8d59-328247057d57 +level: medium +logsource: + product: windows + service: security +modified: 2021/07/07 +status: stable +tags: +- attack.privilege_escalation +- attack.t1078 +- attack.persistence +- attack.t1098 +ruletype: SIGMA diff --git a/test_files/rules/yaml/exclude5.yml b/test_files/rules/yaml/exclude5.yml new file mode 100644 index 00000000..27ec53cc --- /dev/null +++ b/test_files/rules/yaml/exclude5.yml @@ -0,0 +1,31 @@ +title: Local User Creation +author: Patrick Bareiss +date: 2019/04/18 +description: Detects local user creation on windows servers, which shouldn't happen + in an Active Directory environment. Apply this Sigma Use Case on your windows server + logs and not on your DC logs. +detection: + SELECTION_1: + EventID: 4720 + condition: SELECTION_1 +falsepositives: +- Domain Controller Logs +- Local accounts managed by privileged account management tools +fields: +- EventCode +- AccountName +- AccountDomain +id: 66b6be3d-55d0-4f47-9855-d69df21740ea +level: low +logsource: + product: windows + service: security +modified: 2020/08/23 +references: +- https://patrick-bareiss.com/detecting-local-user-creation-in-ad-with-sigma/ +status: experimental +tags: +- attack.persistence +- attack.t1136 +- attack.t1136.001 +ruletype: SIGMA diff --git a/test_files/rules/yaml/noisy1.yml b/test_files/rules/yaml/noisy1.yml new file mode 100644 index 00000000..6ea217b6 --- /dev/null +++ b/test_files/rules/yaml/noisy1.yml @@ -0,0 +1,25 @@ +title: WMI Event Subscription +author: Tom Ueltschi (@c_APT_ure) +date: 2019/01/12 +description: Detects creation of WMI event subscription persistence method +detection: + SELECTION_1: + EventID: 19 + SELECTION_2: + EventID: 20 + SELECTION_3: + EventID: 21 + condition: (SELECTION_1 or SELECTION_2 or SELECTION_3) +falsepositives: +- exclude legitimate (vetted) use of WMI event subscription in your network +id: 0f06a3a5-6a09-413f-8743-e6cf35561297 +level: high +logsource: + category: wmi_event + product: windows +status: experimental +tags: +- attack.t1084 +- attack.persistence +- attack.t1546.003 +ruletype: SIGMA \ No newline at end of file diff --git a/test_files/rules/yaml/noisy2.yml b/test_files/rules/yaml/noisy2.yml new file mode 100644 index 00000000..2296fba4 --- /dev/null +++ b/test_files/rules/yaml/noisy2.yml @@ -0,0 +1,31 @@ +title: Rare Schtasks Creations +author: Florian Roth +date: 2017/03/23 +description: Detects rare scheduled tasks creations that only appear a few times per + time frame and could reveal password dumpers, backdoor installs or other types of + malicious code +detection: + SELECTION_1: + EventID: 4698 + condition: SELECTION_1 | count() by TaskName < 5 +falsepositives: +- Software installation +- Software updates +id: b0d77106-7bb0-41fe-bd94-d1752164d066 +level: low +logsource: + definition: The Advanced Audit Policy setting Object Access > Audit Other Object + Access Events has to be configured to allow this detection (not in the baseline + recommendations by Microsoft). We also recommend extracting the Command field + from the embedded XML in the event data. + product: windows + service: security +status: experimental +tags: +- attack.execution +- attack.privilege_escalation +- attack.persistence +- attack.t1053 +- car.2013-08-001 +- attack.t1053.005 +ruletype: SIGMA diff --git a/test_files/rules/yaml/noisy3.yml b/test_files/rules/yaml/noisy3.yml new file mode 100644 index 00000000..7e2071a0 --- /dev/null +++ b/test_files/rules/yaml/noisy3.yml @@ -0,0 +1,26 @@ +title: Rare Service Installs +author: Florian Roth +date: 2017/03/08 +description: Detects rare service installs that only appear a few times per time frame + and could reveal password dumpers, backdoor installs or other types of malicious + services +detection: + SELECTION_1: + EventID: 7045 + condition: SELECTION_1 | count() by ServiceFileName < 5 +falsepositives: +- Software installation +- Software updates +id: 66bfef30-22a5-4fcd-ad44-8d81e60922ae +level: low +logsource: + product: windows + service: system +status: experimental +tags: +- attack.persistence +- attack.privilege_escalation +- attack.t1050 +- car.2013-09-005 +- attack.t1543.003 +ruletype: SIGMA diff --git a/test_files/rules/yaml/noisy4.yml b/test_files/rules/yaml/noisy4.yml new file mode 100644 index 00000000..39bbd1a3 --- /dev/null +++ b/test_files/rules/yaml/noisy4.yml @@ -0,0 +1,33 @@ +title: Failed Logins with Different Accounts from Single Source System +author: Florian Roth +date: 2017/01/10 +description: Detects suspicious failed logins with different user accounts from a + single source system +detection: + SELECTION_1: + EventID: 529 + SELECTION_2: + EventID: 4625 + SELECTION_3: + TargetUserName: '*' + SELECTION_4: + WorkstationName: '*' + condition: ((SELECTION_1 or SELECTION_2) and SELECTION_3 and SELECTION_4) | count(TargetUserName) + by WorkstationName > 3 +falsepositives: +- Terminal servers +- Jump servers +- Other multiuser systems like Citrix server farms +- Workstations with frequently changing users +id: e98374a6-e2d9-4076-9b5c-11bdb2569995 +level: medium +logsource: + product: windows + service: security +modified: 2021/09/21 +status: experimental +tags: +- attack.persistence +- attack.privilege_escalation +- attack.t1078 +ruletype: SIGMA diff --git a/test_files/rules/yaml/noisy5.yml b/test_files/rules/yaml/noisy5.yml new file mode 100644 index 00000000..ddfc134a --- /dev/null +++ b/test_files/rules/yaml/noisy5.yml @@ -0,0 +1,34 @@ +title: Failed Logins with Different Accounts from Single Source System +author: Florian Roth +date: 2017/01/10 +description: Detects suspicious failed logins with different user accounts from a + single source system +detection: + SELECTION_1: + EventID: 4776 + SELECTION_2: + TargetUserName: '*' + SELECTION_3: + Workstation: '*' + condition: (SELECTION_1 and SELECTION_2 and SELECTION_3) | count(TargetUserName) + by Workstation > 3 +falsepositives: +- Terminal servers +- Jump servers +- Other multiuser systems like Citrix server farms +- Workstations with frequently changing users +id: 6309ffc4-8fa2-47cf-96b8-a2f72e58e538 +level: medium +logsource: + product: windows + service: security +modified: 2021/09/21 +related: +- id: e98374a6-e2d9-4076-9b5c-11bdb2569995 + type: derived +status: experimental +tags: +- attack.persistence +- attack.privilege_escalation +- attack.t1078 +ruletype: SIGMA From a2495b6b50470995075948b2c36f0fca428f44bc Mon Sep 17 00:00:00 2001 From: kazuminn Date: Thu, 9 Dec 2021 01:35:53 +0900 Subject: [PATCH 12/12] fix miss --- src/yaml.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yaml.rs b/src/yaml.rs index 7420410c..0e9ad2e8 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -264,7 +264,7 @@ mod tests { #[test] fn test_exclude_rules_file() { let mut yaml = yaml::ParseYaml::new(); - let path = Path::new("test_files/rules/"); + let path = Path::new("test_files/rules/yaml"); yaml.read_dir(path.to_path_buf(), &"", &fillter::exclude_ids()) .unwrap(); assert_eq!(yaml.ignorerule_count, 10);