diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 1904d5fe..10a1542a 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; +use crate::filter; use crate::yaml::ParseYaml; use std::sync::Arc; @@ -55,12 +55,12 @@ impl Detection { pub fn parse_rule_files( level: String, rulespath: Option<&str>, - fill_ids: &fillter::RuleFill, + exclude_ids: &filter::RuleExclude, ) -> Vec { // ルールファイルのパースを実行 let mut rulefile_loader = ParseYaml::new(); let result_readdir = - rulefile_loader.read_dir(rulespath.unwrap_or(DIRPATH_RULES), &level, fill_ids); + rulefile_loader.read_dir(rulespath.unwrap_or(DIRPATH_RULES), &level, exclude_ids); if result_readdir.is_err() { AlertMessage::alert( &mut std::io::stderr().lock(), @@ -275,7 +275,6 @@ impl Detection { fn test_parse_rule_files() { let level = "informational"; let opt_rule_path = Some("./test_files/rules/level_yaml"); - let cole = - Detection::parse_rule_files(level.to_owned(), opt_rule_path, &fillter::exclude_ids()); + let cole = Detection::parse_rule_files(level.to_owned(), opt_rule_path, &filter::exclude_ids()); assert_eq!(5, cole.len()); } diff --git a/src/fillter.rs b/src/fillter.rs deleted file mode 100644 index 7b61d175..00000000 --- a/src/fillter.rs +++ /dev/null @@ -1,36 +0,0 @@ -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/filter.rs b/src/filter.rs new file mode 100644 index 00000000..113283cf --- /dev/null +++ b/src/filter.rs @@ -0,0 +1,44 @@ +use crate::detections::configs; +use std::collections::HashSet; +use std::fs; + +#[derive(Clone, Debug)] +pub struct RuleExclude { + pub no_use_rule: HashSet, +} + +pub fn exclude_ids() -> RuleExclude { + let mut ids; + match fs::read("config/exclude-rules.txt") { + Ok(file) => ids = String::from_utf8(file).unwrap(), + Err(_) => panic!("config/exclude-rules.txt does not exist"), + }; + + if !configs::CONFIG + .read() + .unwrap() + .args + .is_present("show-noisyalerts") + { + ids += "\n"; // 改行を入れないとexclude-rulesの一番最後の行とnoisy-rules.txtの一番最初の行が一行にまとめられてしまう。 + match fs::read("config/noisy-rules.txt") { + Ok(file) => ids += &String::from_utf8(file).unwrap(), + Err(_) => panic!("config/noisy-rules.txt does not exist"), + }; + } + + let mut exclude_ids = RuleExclude { + no_use_rule: HashSet::new(), + }; + + for v in ids.split_whitespace() { + let v = v.to_string(); + if v.is_empty() { + // 空行は無視する。 + continue; + } + exclude_ids.no_use_rule.insert(v); + } + + return exclude_ids; +} diff --git a/src/lib.rs b/src/lib.rs index 9bf20692..9bd8f144 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ pub mod afterfact; pub mod detections; -pub mod fillter; +pub mod filter; pub mod notify; pub mod omikuji; pub mod timeline; diff --git a/src/main.rs b/src/main.rs index 56b4b6c5..b28c350c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use evtx::{EvtxParser, ParserSettings}; use hayabusa::detections::detection; use hayabusa::detections::detection::EvtxRecordInfo; use hayabusa::detections::print::AlertMessage; -use hayabusa::fillter; +use hayabusa::filter; use hayabusa::omikuji::Omikuji; use hayabusa::{afterfact::after_fact, detections::utils}; use hayabusa::{detections::configs, timeline::timeline::Timeline}; @@ -133,7 +133,7 @@ fn analysis_files(evtx_files: Vec) { let rule_files = detection::Detection::parse_rule_files( level, configs::CONFIG.read().unwrap().args.value_of("rules"), - &fillter::exclude_ids(), + &filter::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 0e9ad2e8..33b50a6a 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -3,7 +3,7 @@ extern crate yaml_rust; use crate::detections::configs; use crate::detections::print::AlertMessage; -use crate::fillter::RuleFill; +use crate::filter::RuleExclude; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; @@ -47,14 +47,14 @@ impl ParseYaml { &mut self, path: P, level: &str, - fill_ids: &RuleFill, + exclude_ids: &RuleExclude, ) -> 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)?; + self.read_dir(entry.path(), level, exclude_ids)?; return io::Result::Ok(ret); } // ファイル以外は無視 @@ -140,7 +140,10 @@ impl ParseYaml { //除外されたルールは無視する 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()) { + match exclude_ids + .no_use_rule + .get(&rule_id.unwrap_or("").to_string()) + { None => (), Some(_) => { self.ignorerule_count += 1; @@ -160,9 +163,9 @@ impl ParseYaml { #[cfg(test)] mod tests { - use crate::fillter; + use crate::filter; use crate::yaml; - use crate::yaml::RuleFill; + use crate::yaml::RuleExclude; use std::collections::HashSet; use std::path::Path; use yaml_rust::YamlLoader; @@ -170,13 +173,13 @@ mod tests { #[test] fn test_read_dir_yaml() { let mut yaml = yaml::ParseYaml::new(); - let fill_ids = RuleFill { + let exclude_ids = RuleExclude { no_use_rule: HashSet::new(), }; let _ = &yaml.read_dir( "test_files/rules/yaml/".to_string(), &"".to_owned(), - &fill_ids, + &exclude_ids, ); assert_ne!(yaml.files.len(), 0); } @@ -212,7 +215,7 @@ 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(), &"", &fillter::exclude_ids()) + yaml.read_dir(path.to_path_buf(), &"", &filter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 5); } @@ -221,19 +224,15 @@ 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(), - &"informational", - &fillter::exclude_ids(), - ) - .unwrap(); + yaml.read_dir(path.to_path_buf(), &"informational", &filter::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"); - yaml.read_dir(path.to_path_buf(), &"LOW", &fillter::exclude_ids()) + yaml.read_dir(path.to_path_buf(), &"LOW", &filter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 4); } @@ -241,7 +240,7 @@ mod tests { 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", &fillter::exclude_ids()) + yaml.read_dir(path.to_path_buf(), &"MEDIUM", &filter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 3); } @@ -249,7 +248,7 @@ mod tests { 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", &fillter::exclude_ids()) + yaml.read_dir(path.to_path_buf(), &"HIGH", &filter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 2); } @@ -257,16 +256,27 @@ mod tests { 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", &fillter::exclude_ids()) + yaml.read_dir(path.to_path_buf(), &"CRITICAL", &filter::exclude_ids()) .unwrap(); assert_eq!(yaml.files.len(), 1); } #[test] - fn test_exclude_rules_file() { + fn test_all_exclude_rules_file() { let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/yaml"); - yaml.read_dir(path.to_path_buf(), &"", &fillter::exclude_ids()) + yaml.read_dir(path.to_path_buf(), &"", &filter::exclude_ids()) .unwrap(); assert_eq!(yaml.ignorerule_count, 10); } + #[test] + fn test_none_exclude_rules_file() { + let mut yaml = yaml::ParseYaml::new(); + let path = Path::new("test_files/rules/yaml"); + let exclude_ids = RuleExclude { + no_use_rule: HashSet::new(), + }; + yaml.read_dir(path.to_path_buf(), &"", &exclude_ids) + .unwrap(); + assert_eq!(yaml.ignorerule_count, 0); + } }