From 79ce6618f50c8481b26adae9ef45904fc42dccb3 Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Sun, 7 Jul 2024 22:06:42 +0900 Subject: [PATCH 01/15] refactor: remove unused fields/params --- src/detections/detection.rs | 9 ++--- src/detections/rule/count.rs | 69 +----------------------------------- src/detections/rule/mod.rs | 4 --- 3 files changed, 4 insertions(+), 78 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 53d42567f..3efafdbec 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -1313,7 +1313,7 @@ mod tests { fn test_output_aggregation_output_with_output() { let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); let agg_result: AggResult = - AggResult::new(2, "_".to_string(), vec![], default_time, ">= 1".to_string()); + AggResult::new(2, "_".to_string(), vec![], default_time); let rule_str = r#" enabled: true detection: @@ -1341,7 +1341,7 @@ mod tests { fn test_output_aggregation_output_no_filed_by() { let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); let agg_result: AggResult = - AggResult::new(2, "_".to_string(), vec![], default_time, ">= 1".to_string()); + AggResult::new(2, "_".to_string(), vec![], default_time); let rule_str = r#" enabled: true detection: @@ -1368,7 +1368,7 @@ mod tests { fn test_output_aggregation_output_with_timeframe() { let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); let agg_result: AggResult = - AggResult::new(2, "_".to_string(), vec![], default_time, ">= 1".to_string()); + AggResult::new(2, "_".to_string(), vec![], default_time); let rule_str = r#" enabled: true detection: @@ -1400,7 +1400,6 @@ mod tests { "_".to_string(), vec!["7040".to_owned(), "9999".to_owned()], default_time, - ">= 1".to_string(), ); let rule_str = r#" enabled: true @@ -1430,7 +1429,6 @@ mod tests { "lsass.exe".to_string(), vec!["0000".to_owned(), "1111".to_owned()], default_time, - ">= 1".to_string(), ); let rule_str = r#" enabled: true @@ -1459,7 +1457,6 @@ mod tests { "lsass.exe".to_string(), vec![], default_time, - ">= 1".to_string(), ); let rule_str = r#" enabled: true diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index 76236f558..bf2363368 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -188,36 +188,6 @@ pub fn aggregation_condition_select( ret } -/// aggregation condition内での条件式を文字として返す関数 -pub fn get_str_agg_eq(rule: &RuleNode) -> String { - //この関数はaggregation ruleのパースが正常終了した後に呼ばれる想定のためOptionの判定は行わない - let agg_condition = rule.detection.aggregation_condition.as_ref().unwrap(); - let mut ret: String = String::default(); - match agg_condition._cmp_op { - AggregationConditionToken::EQ => { - ret.push_str("== "); - } - AggregationConditionToken::GE => { - ret.push_str(">= "); - } - AggregationConditionToken::LE => { - ret.push_str("<= "); - } - AggregationConditionToken::GT => { - ret.push_str("> "); - } - AggregationConditionToken::LT => { - ret.push_str("< "); - } - _ => { - //想定しない演算子のため、空白文字で対応するものがない - return "".to_string(); - } - } - ret.push_str(&agg_condition._cmp_num.to_string()); - ret -} - #[derive(Clone, Debug)] /// countの括弧内の情報とレコードの情報を所持する構造体 pub struct AggRecordTimeInfo { @@ -354,7 +324,6 @@ trait CountStrategy { datas: &[AggRecordTimeInfo], cnt: i64, key: &str, - rule: &RuleNode, ) -> AggResult; } @@ -411,7 +380,6 @@ impl CountStrategy for FieldStrategy { datas: &[AggRecordTimeInfo], _cnt: i64, key: &str, - rule: &RuleNode, ) -> AggResult { let values: Vec = self.value_2_cnt.drain().map(|(key, _)| key).collect(); // drainで初期化 AggResult::new( @@ -419,7 +387,6 @@ impl CountStrategy for FieldStrategy { key.to_string(), values, datas[left as usize].record_time, - get_str_agg_eq(rule), ) } } @@ -458,14 +425,12 @@ impl CountStrategy for NoFieldStrategy { datas: &[AggRecordTimeInfo], cnt: i64, key: &str, - rule: &RuleNode, ) -> AggResult { let ret = AggResult::new( cnt, key.to_string(), vec![], datas[left as usize].record_time, - get_str_agg_eq(rule), ); self.cnt = 0; //cntを初期化 ret @@ -541,7 +506,7 @@ pub fn judge_timeframe( let cnt = counter.count(); if select_aggcon(cnt, rule) { // 条件を満たすtimeframeが見つかった - ret.push(counter.create_agg_result(left, &datas, cnt, key, rule)); + ret.push(counter.create_agg_result(left, &datas, cnt, key)); left = right; } else { // 条件を満たさなかったので、rightとleftを+1ずらす @@ -710,7 +675,6 @@ mod tests { "_".to_string(), vec![], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), - ">= 1".to_string(), )]; check_count( rule_str, @@ -763,14 +727,12 @@ mod tests { "_".to_string(), vec![], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), - ">= 1".to_string(), ), AggResult::new( 1, "_".to_string(), vec![], Utc.with_ymd_and_hms(1996, 2, 27, 1, 5, 1).unwrap(), - ">= 1".to_string(), ), ]; check_count( @@ -803,7 +765,6 @@ mod tests { "_".to_string(), vec!["System".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), - ">= 1".to_string(), ); check_count( rule_str, @@ -853,14 +814,12 @@ mod tests { "System".to_owned(), vec!["7040".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), - ">= 1".to_string(), ), AggResult::new( 1, "Test".to_owned(), vec!["9999".to_owned()], Utc.with_ymd_and_hms(1996, 2, 27, 1, 5, 1).unwrap(), - ">= 1".to_string(), ), ]; check_count( @@ -911,14 +870,12 @@ mod tests { "Windows Event Log".to_owned(), vec!["7040".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), - ">= 1".to_string(), ), AggResult::new( 1, "Test".to_owned(), vec!["9999".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 5, 0).unwrap(), - ">= 1".to_string(), ), ]; check_count( @@ -1031,7 +988,6 @@ mod tests { "System".to_owned(), vec!["7040".to_owned(), "9999".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), - ">= 2".to_string(), )]; check_count( rule_str, @@ -1081,7 +1037,6 @@ mod tests { "System".to_owned(), vec!["7040".to_owned(), "9999".to_owned()], default_time, - ">= 1".to_string(), )]; check_count( rule_str, @@ -1111,7 +1066,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1145,7 +1099,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1179,7 +1132,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1195,7 +1147,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1219,7 +1170,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1253,7 +1203,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1287,7 +1236,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1327,7 +1275,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1367,7 +1314,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1415,7 +1361,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned()], default_time, - ">= 1".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1437,7 +1382,6 @@ mod tests { "Windows Event Log".to_owned(), vec!["1".to_owned()], default_time, - ">= 1".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1475,7 +1419,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], Utc.with_ymd_and_hms(1977, 1, 9, 1, 30, 0).unwrap(), - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1526,7 +1469,6 @@ mod tests { "4".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 1, 30, 0).unwrap(), - ">= 4".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); @@ -1554,7 +1496,6 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], Utc.with_ymd_and_hms(1977, 1, 9, 1, 30, 0).unwrap(), - ">= 3".to_string(), )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); @@ -1604,7 +1545,6 @@ mod tests { "4".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 1, 30, 0).unwrap(), - ">= 4".to_string(), ), AggResult::new( 4, @@ -1616,7 +1556,6 @@ mod tests { "4".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 5, 30, 0).unwrap(), - ">= 4".to_string(), ), AggResult::new( 4, @@ -1628,7 +1567,6 @@ mod tests { "4".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 9, 30, 0).unwrap(), - ">= 4".to_string(), ), ]; @@ -1666,7 +1604,6 @@ mod tests { "_".to_owned(), vec!["2".to_owned(), "3".to_owned(), "4".to_owned()], Utc.with_ymd_and_hms(1977, 1, 9, 3, 30, 0).unwrap(), - ">= 3".to_string(), ), AggResult::new( 4, @@ -1678,7 +1615,6 @@ mod tests { "5".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 20, 00, 0).unwrap(), - ">= 3".to_string(), ), ]; check_count(&rule_str, &recs, expected_count, expected_agg_result); @@ -1773,7 +1709,6 @@ mod tests { let mut expect_key = vec![]; let mut expect_field_values = vec![]; let mut expect_start_timedate = vec![]; - let mut expect_condition_op_num = vec![]; for expect_agg in expect_agg_results { let expect_count = expected_counts.get(&expect_agg.key).unwrap_or(&-1); //countupの関数が機能しているかを確認 @@ -1785,7 +1720,6 @@ mod tests { expect_key.push(expect_agg.key); expect_field_values.push(expect_agg.field_values); expect_start_timedate.push(expect_agg.start_timedate); - expect_condition_op_num.push(expect_agg.condition_op_num); } for agg_result in agg_results { println!("{}", &agg_result.start_timedate); @@ -1801,7 +1735,6 @@ mod tests { // field`要素の順番については以降の処理で関連しない assert!(agg_result.field_values.contains(expect_field_value)); } - assert_eq!(agg_result.condition_op_num, expect_condition_op_num[index]); } } } diff --git a/src/detections/rule/mod.rs b/src/detections/rule/mod.rs index a154488dc..622ab372d 100644 --- a/src/detections/rule/mod.rs +++ b/src/detections/rule/mod.rs @@ -381,8 +381,6 @@ pub struct AggResult { pub field_values: Vec, ///検知したブロックの最初のレコードの時間 pub start_timedate: DateTime, - ///条件式の情報 - pub condition_op_num: String, } impl AggResult { @@ -391,14 +389,12 @@ impl AggResult { key_name: String, field_value: Vec, event_start_timedate: DateTime, - condition_op_number: String, ) -> AggResult { AggResult { data: count_data, key: key_name, field_values: field_value, start_timedate: event_start_timedate, - condition_op_num: condition_op_number, } } } From 2b60013c3c2a31ffafb46760fe29167a7b7300fd Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Tue, 9 Jul 2024 02:14:20 +0900 Subject: [PATCH 02/15] fix: count up events when agg/correlation rule matched event --- src/afterfact.rs | 51 ++++++++++++++--------- src/detections/detection.rs | 20 ++++----- src/detections/message.rs | 8 ++-- src/detections/rule/count.rs | 79 ++++++++++++++++++++++++------------ src/detections/rule/mod.rs | 6 ++- 5 files changed, 101 insertions(+), 63 deletions(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index 2289753ad..3b82a2d3e 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -495,15 +495,26 @@ fn calc_statistic_info( afterfact_info .timestamps .push(detect_info.detected_time.timestamp()); - if !detect_info.is_condition { - afterfact_info - .detected_record_idset - .insert(CompactString::from(format!( - "{}_{}", - detect_info.detected_time, detect_info.eventid - ))); + match &detect_info.agg_result { + None => { + afterfact_info + .detected_record_idset + .insert(CompactString::from(format!( + "{}_{}", + detect_info.detected_time, detect_info.eventid + ))); + } + Some(agg_result) => { + agg_result.agg_record_time_info.iter().for_each(|a| { + afterfact_info + .detected_record_idset + .insert(CompactString::from(format!( + "{}_{}", + a.record_time, a.record_event_id + ))); + }); + } } - if !output_option.no_summary { let level_suffix = get_level_suffix(detect_info.level.as_str()); let author_list = afterfact_info @@ -1887,7 +1898,7 @@ pub fn output_json_str( let mut children_output_stock: HashMap> = HashMap::new(); let mut children_output_order = vec![]; - if detect_info.is_condition { + if detect_info.agg_result.is_some() { if details_target_stock[0] == "-" { output_stock.push(_create_json_output_format( key, @@ -2463,7 +2474,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map: HashMap::default(), }, &profile_converter, @@ -2487,7 +2498,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map: HashMap::default(), }, &profile_converter, @@ -2810,7 +2821,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map: HashMap::default(), }, &profile_converter, @@ -2834,7 +2845,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map: HashMap::default(), }, &profile_converter, @@ -3137,7 +3148,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map: HashMap::default(), }, &profile_converter, @@ -3161,7 +3172,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map: HashMap::default(), }, &profile_converter, @@ -3474,7 +3485,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map, }, &profile_converter, @@ -3498,7 +3509,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map: HashMap::default(), }, &profile_converter, @@ -3883,7 +3894,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map, }, &profile_converter, @@ -4237,7 +4248,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map, }, &profile_converter, @@ -4517,7 +4528,7 @@ mod tests { eventid: CompactString::from(test_eventid), detail: CompactString::default(), ext_field: output_profile.to_owned(), - is_condition: false, + agg_result: None, details_convert_map, }, &profile_converter, diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 3efafdbec..9c8d332e0 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -742,7 +742,7 @@ impl Detection { eventid: eid, detail: CompactString::default(), ext_field: stored_static.profiles.as_ref().unwrap().to_owned(), - is_condition: false, + agg_result: None, details_convert_map: HashMap::default(), }; @@ -965,7 +965,7 @@ impl Detection { eventid: CompactString::from("-"), detail: output, ext_field: stored_static.profiles.as_ref().unwrap().to_owned(), - is_condition: true, + agg_result: Some(agg_result), details_convert_map: HashMap::default(), }; let binding = STORED_EKEY_ALIAS.read().unwrap(); @@ -1313,7 +1313,7 @@ mod tests { fn test_output_aggregation_output_with_output() { let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); let agg_result: AggResult = - AggResult::new(2, "_".to_string(), vec![], default_time); + AggResult::new(2, "_".to_string(), vec![], default_time, vec![]); let rule_str = r#" enabled: true detection: @@ -1341,7 +1341,7 @@ mod tests { fn test_output_aggregation_output_no_filed_by() { let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); let agg_result: AggResult = - AggResult::new(2, "_".to_string(), vec![], default_time); + AggResult::new(2, "_".to_string(), vec![], default_time, vec![]); let rule_str = r#" enabled: true detection: @@ -1368,7 +1368,7 @@ mod tests { fn test_output_aggregation_output_with_timeframe() { let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); let agg_result: AggResult = - AggResult::new(2, "_".to_string(), vec![], default_time); + AggResult::new(2, "_".to_string(), vec![], default_time, vec![]); let rule_str = r#" enabled: true detection: @@ -1400,6 +1400,7 @@ mod tests { "_".to_string(), vec!["7040".to_owned(), "9999".to_owned()], default_time, + vec![], ); let rule_str = r#" enabled: true @@ -1429,6 +1430,7 @@ mod tests { "lsass.exe".to_string(), vec!["0000".to_owned(), "1111".to_owned()], default_time, + vec![], ); let rule_str = r#" enabled: true @@ -1452,12 +1454,8 @@ mod tests { #[test] fn test_output_aggregation_output_with_by() { let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); - let agg_result: AggResult = AggResult::new( - 2, - "lsass.exe".to_string(), - vec![], - default_time, - ); + let agg_result: AggResult = + AggResult::new(2, "lsass.exe".to_string(), vec![], default_time, vec![]); let rule_str = r#" enabled: true detection: diff --git a/src/detections/message.rs b/src/detections/message.rs index 0f0b841d4..d246ba04b 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -1,6 +1,9 @@ extern crate lazy_static; +use super::configs::EventKeyAliasConfig; +use super::utils::remove_sp_char; use crate::detections::configs::CURRENT_EXE_PATH; use crate::detections::field_data_map::{convert_field_data, FieldDataMap, FieldDataMapKey}; +use crate::detections::rule::AggResult; use crate::detections::utils::{self, get_serde_number_to_string, write_color_buffer}; use crate::options::profile::Profile::{ self, AllFieldInfo, Details, ExtraFieldInfo, Literal, SrcASN, SrcCity, SrcCountry, TgtASN, @@ -23,9 +26,6 @@ use std::path::Path; use std::sync::Mutex; use termcolor::{BufferWriter, ColorChoice}; -use super::configs::EventKeyAliasConfig; -use super::utils::remove_sp_char; - /* * This struct express log record */ @@ -40,7 +40,7 @@ pub struct DetectInfo { pub eventid: CompactString, pub detail: CompactString, pub ext_field: Vec<(CompactString, Profile)>, - pub is_condition: bool, + pub agg_result: Option, pub details_convert_map: HashMap>, } diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index bf2363368..287df196f 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -50,13 +50,7 @@ pub fn count( STORED_EKEY_ALIAS.read().unwrap().as_ref().unwrap(), ) .unwrap_or_default(); - let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); - countup( - rule, - key, - field_value, - message::get_event_time(record, json_input_flag).unwrap_or(default_time), - ); + countup(rule, key, field_value, record, json_input_flag); } ///count byの条件に合致する検知済みレコードの数を増やすための関数 @@ -64,12 +58,24 @@ pub fn countup( rule: &mut RuleNode, key: String, field_value: String, - record_time_value: DateTime, + record: &Value, + json_input_flag: bool, ) { + let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); + let record_time_value = + message::get_event_time(record, json_input_flag).unwrap_or(default_time); + let event_id = utils::get_event_value( + &utils::get_event_id_key(), + record, + STORED_EKEY_ALIAS.read().unwrap().as_ref().unwrap(), + ) + .unwrap(); + let event_id = event_id.to_string(); let value_map = rule.countdata.entry(key).or_default(); value_map.push(AggRecordTimeInfo { field_record_value: field_value, record_time: record_time_value, + record_event_id: event_id, }); } @@ -188,11 +194,12 @@ pub fn aggregation_condition_select( ret } -#[derive(Clone, Debug)] +#[derive(Debug, Clone, PartialEq, Eq, Default)] /// countの括弧内の情報とレコードの情報を所持する構造体 pub struct AggRecordTimeInfo { pub field_record_value: String, pub record_time: DateTime, + pub record_event_id: String, } #[derive(Debug)] @@ -318,13 +325,7 @@ trait CountStrategy { /** * AggResultを作成します。 */ - fn create_agg_result( - &mut self, - left: i64, - datas: &[AggRecordTimeInfo], - cnt: i64, - key: &str, - ) -> AggResult; + fn create_agg_result(&mut self, datas: &[AggRecordTimeInfo], cnt: i64, key: &str) -> AggResult; } /** @@ -376,7 +377,6 @@ impl CountStrategy for FieldStrategy { fn create_agg_result( &mut self, - left: i64, datas: &[AggRecordTimeInfo], _cnt: i64, key: &str, @@ -386,7 +386,8 @@ impl CountStrategy for FieldStrategy { values.len() as i64, key.to_string(), values, - datas[left as usize].record_time, + datas.first().unwrap().record_time, + datas.to_vec(), ) } } @@ -419,18 +420,13 @@ impl CountStrategy for NoFieldStrategy { self.cnt } - fn create_agg_result( - &mut self, - left: i64, - datas: &[AggRecordTimeInfo], - cnt: i64, - key: &str, - ) -> AggResult { + fn create_agg_result(&mut self, datas: &[AggRecordTimeInfo], cnt: i64, key: &str) -> AggResult { let ret = AggResult::new( cnt, key.to_string(), vec![], - datas[left as usize].record_time, + datas.first().unwrap().record_time, + datas.to_vec(), ); self.cnt = 0; //cntを初期化 ret @@ -506,7 +502,7 @@ pub fn judge_timeframe( let cnt = counter.count(); if select_aggcon(cnt, rule) { // 条件を満たすtimeframeが見つかった - ret.push(counter.create_agg_result(left, &datas, cnt, key)); + ret.push(counter.create_agg_result(&datas[left as usize..right as usize], cnt, key)); left = right; } else { // 条件を満たさなかったので、rightとleftを+1ずらす @@ -675,6 +671,7 @@ mod tests { "_".to_string(), vec![], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), + vec![], )]; check_count( rule_str, @@ -727,12 +724,14 @@ mod tests { "_".to_string(), vec![], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), + vec![], ), AggResult::new( 1, "_".to_string(), vec![], Utc.with_ymd_and_hms(1996, 2, 27, 1, 5, 1).unwrap(), + vec![], ), ]; check_count( @@ -765,6 +764,7 @@ mod tests { "_".to_string(), vec!["System".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), + vec![], ); check_count( rule_str, @@ -814,12 +814,14 @@ mod tests { "System".to_owned(), vec!["7040".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), + vec![], ), AggResult::new( 1, "Test".to_owned(), vec!["9999".to_owned()], Utc.with_ymd_and_hms(1996, 2, 27, 1, 5, 1).unwrap(), + vec![], ), ]; check_count( @@ -870,12 +872,14 @@ mod tests { "Windows Event Log".to_owned(), vec!["7040".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), + vec![], ), AggResult::new( 1, "Test".to_owned(), vec!["9999".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 5, 0).unwrap(), + vec![], ), ]; check_count( @@ -988,6 +992,7 @@ mod tests { "System".to_owned(), vec!["7040".to_owned(), "9999".to_owned()], Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(), + vec![], )]; check_count( rule_str, @@ -1037,6 +1042,7 @@ mod tests { "System".to_owned(), vec!["7040".to_owned(), "9999".to_owned()], default_time, + vec![], )]; check_count( rule_str, @@ -1066,6 +1072,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1099,6 +1106,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1132,6 +1140,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1147,6 +1156,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1170,6 +1180,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1203,6 +1214,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1236,6 +1248,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1275,6 +1288,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1314,6 +1328,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1361,6 +1376,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1382,6 +1398,7 @@ mod tests { "Windows Event Log".to_owned(), vec!["1".to_owned()], default_time, + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1419,6 +1436,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], Utc.with_ymd_and_hms(1977, 1, 9, 1, 30, 0).unwrap(), + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); } @@ -1469,6 +1487,7 @@ mod tests { "4".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 1, 30, 0).unwrap(), + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); @@ -1496,6 +1515,7 @@ mod tests { "_".to_owned(), vec!["1".to_owned(), "2".to_owned(), "3".to_owned()], Utc.with_ymd_and_hms(1977, 1, 9, 1, 30, 0).unwrap(), + vec![], )]; check_count(&rule_str, &recs, expected_count, expected_agg_result); @@ -1545,6 +1565,7 @@ mod tests { "4".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 1, 30, 0).unwrap(), + vec![], ), AggResult::new( 4, @@ -1556,6 +1577,7 @@ mod tests { "4".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 5, 30, 0).unwrap(), + vec![], ), AggResult::new( 4, @@ -1567,6 +1589,7 @@ mod tests { "4".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 9, 30, 0).unwrap(), + vec![], ), ]; @@ -1604,6 +1627,7 @@ mod tests { "_".to_owned(), vec!["2".to_owned(), "3".to_owned(), "4".to_owned()], Utc.with_ymd_and_hms(1977, 1, 9, 3, 30, 0).unwrap(), + vec![], ), AggResult::new( 4, @@ -1615,6 +1639,7 @@ mod tests { "5".to_owned(), ], Utc.with_ymd_and_hms(1977, 1, 9, 20, 00, 0).unwrap(), + vec![], ), ]; check_count(&rule_str, &recs, expected_count, expected_agg_result); diff --git a/src/detections/rule/mod.rs b/src/detections/rule/mod.rs index 622ab372d..c8f17eb7d 100644 --- a/src/detections/rule/mod.rs +++ b/src/detections/rule/mod.rs @@ -370,7 +370,7 @@ impl DetectionNode { } } -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq, Eq, Default)] /// countなどのaggregationの結果を出力する構造体 pub struct AggResult { /// countなどの値 @@ -381,6 +381,8 @@ pub struct AggResult { pub field_values: Vec, ///検知したブロックの最初のレコードの時間 pub start_timedate: DateTime, + ///検知したブロックのレコードの全時間とEventID + pub agg_record_time_info: Vec, } impl AggResult { @@ -389,12 +391,14 @@ impl AggResult { key_name: String, field_value: Vec, event_start_timedate: DateTime, + agg_record_time_info: Vec, ) -> AggResult { AggResult { data: count_data, key: key_name, field_values: field_value, start_timedate: event_start_timedate, + agg_record_time_info, } } } From 12b3f6e782f84318cc5bf1fb86bce09f607a8486 Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Tue, 9 Jul 2024 22:19:16 +0900 Subject: [PATCH 03/15] chg: output channel/event_id/computer when agg/correlation result --- src/afterfact.rs | 97 ++++++++++++++++++++++-------------- src/detections/detection.rs | 50 +++++++++++++++++-- src/detections/rule/count.rs | 53 +++++++++++++------- src/detections/rule/mod.rs | 2 +- 4 files changed, 142 insertions(+), 60 deletions(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index 3b82a2d3e..a25403ade 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -508,10 +508,7 @@ fn calc_statistic_info( agg_result.agg_record_time_info.iter().for_each(|a| { afterfact_info .detected_record_idset - .insert(CompactString::from(format!( - "{}_{}", - a.record_time, a.record_event_id - ))); + .insert(CompactString::from(format!("{}_{}", a.time, a.event_id))); }); } } @@ -550,44 +547,70 @@ fn calc_statistic_info( .insert(detect_info.ruleid.to_owned()); afterfact_info.unique_detect_counts_by_level[level_suffix] += 1; } - - let computer_rule_check_key = CompactString::from(format!( - "{}|{}", - &detect_info.computername, &detect_info.rulepath - )); - if !afterfact_info - .detected_computer_and_rule_names - .contains(&computer_rule_check_key) - { - afterfact_info - .detected_computer_and_rule_names - .insert(computer_rule_check_key); - countup_aggregation( - &mut afterfact_info.detect_counts_by_computer_and_level, - &detect_info.level, - &detect_info.computername, - ); + match &detect_info.agg_result { + None => { + update_afterfact_aggregations( + detect_info, + &detect_info.computername, + afterfact_info, + output_option, + ); + } + Some(agg_result) => { + for a in agg_result.agg_record_time_info.iter() { + update_afterfact_aggregations( + detect_info, + &CompactString::from(a.computer.clone()), + afterfact_info, + output_option, + ); + } + } } - afterfact_info.rule_title_path_map.insert( - detect_info.ruletitle.to_owned(), - detect_info.rulepath.to_owned(), - ); - - countup_aggregation( - &mut afterfact_info.detect_counts_by_date_and_level, - &detect_info.level, - &format_time(&detect_info.detected_time, true, output_option), - ); - countup_aggregation( - &mut afterfact_info.detect_counts_by_rule_and_level, - &detect_info.level, - &detect_info.ruletitle, - ); - afterfact_info.total_detect_counts_by_level[level_suffix] += 1; } } } +fn update_afterfact_aggregations( + detect_info: &DetectInfo, + computername: &CompactString, + afterfact_info: &mut AfterfactInfo, + output_option: &OutputOption, +) { + let computer_rule_check_key = + CompactString::from(format!("{}|{}", computername, &detect_info.rulepath)); + if !afterfact_info + .detected_computer_and_rule_names + .contains(&computer_rule_check_key) + { + afterfact_info + .detected_computer_and_rule_names + .insert(computer_rule_check_key); + countup_aggregation( + &mut afterfact_info.detect_counts_by_computer_and_level, + &detect_info.level, + computername, + ); + } + afterfact_info.rule_title_path_map.insert( + detect_info.ruletitle.to_owned(), + detect_info.rulepath.to_owned(), + ); + + countup_aggregation( + &mut afterfact_info.detect_counts_by_date_and_level, + &detect_info.level, + &format_time(&detect_info.detected_time, true, output_option), + ); + countup_aggregation( + &mut afterfact_info.detect_counts_by_rule_and_level, + &detect_info.level, + &detect_info.ruletitle, + ); + let level_suffix = get_level_suffix(detect_info.level.as_str()); + afterfact_info.total_detect_counts_by_level[level_suffix] += 1; +} + pub fn output_additional_afterfact( stored_static: &StoredStatic, afterfact_writer: &mut AfterfactWriter, diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 9c8d332e0..bcebb50c5 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -1,5 +1,6 @@ extern crate csv; +use std::collections::HashSet; use std::default::Default; use std::fmt::Write; use std::path::Path; @@ -771,7 +772,6 @@ impl Detection { let mut profile_converter: HashMap<&str, Profile> = HashMap::new(); let level = rule.yaml["level"].as_str().unwrap_or("-").to_string(); let tags_config_values: Vec<&CompactString> = TAGS_CONFIG.values().collect(); - let is_json_timeline = matches!(stored_static.config.action, Some(Action::JsonTimeline(_))); for (key, profile) in stored_static.profiles.as_ref().unwrap().iter() { match profile { @@ -789,10 +789,38 @@ impl Detection { ); } Computer(_) => { - profile_converter.insert(key.as_str(), Computer("-".into())); + profile_converter.insert( + key.as_str(), + Computer( + agg_result + .agg_record_time_info + .iter() + .map(|x| x.computer.clone()) + .collect::>() // HashSetに変換して重複を削除 + .iter() + .cloned() + .collect::>() + .join(" ¦ ") + .into(), + ), + ); } Channel(_) => { - profile_converter.insert(key.as_str(), Channel("-".into())); + profile_converter.insert( + key.as_str(), + Channel( + agg_result + .agg_record_time_info + .iter() + .map(|x| x.channel.clone()) + .collect::>() // HashSetに変換して重複を削除 + .iter() + .cloned() + .collect::>() + .join(" ¦ ") + .into(), + ), + ); } Level(_) => { let str_level = level.as_str(); @@ -805,7 +833,21 @@ impl Detection { profile_converter.insert(key.as_str(), Level(prof_level.to_string().into())); } EventID(_) => { - profile_converter.insert(key.as_str(), EventID("-".into())); + profile_converter.insert( + key.as_str(), + EventID( + agg_result + .agg_record_time_info + .iter() + .map(|x| x.event_id.clone()) + .collect::>() // HashSetに変換して重複を削除 + .iter() + .cloned() + .collect::>() + .join(" ¦ ") + .into(), + ), + ); } RecordID(_) => { profile_converter.insert(key.as_str(), RecordID("-".into())); diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index 287df196f..de5d5959c 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -62,20 +62,35 @@ pub fn countup( json_input_flag: bool, ) { let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); - let record_time_value = - message::get_event_time(record, json_input_flag).unwrap_or(default_time); + let time = message::get_event_time(record, json_input_flag).unwrap_or(default_time); let event_id = utils::get_event_value( - &utils::get_event_id_key(), + "Event.System.EventID", record, STORED_EKEY_ALIAS.read().unwrap().as_ref().unwrap(), ) .unwrap(); let event_id = event_id.to_string(); + let computer = utils::get_event_value( + "Event.System.Computer", + record, + STORED_EKEY_ALIAS.read().unwrap().as_ref().unwrap(), + ) + .unwrap(); + let computer = computer.to_string().trim_matches('\"').to_string(); + let channel = utils::get_event_value( + "Event.System.Channel", + record, + STORED_EKEY_ALIAS.read().unwrap().as_ref().unwrap(), + ) + .unwrap(); + let channel = channel.to_string().trim_matches('\"').to_string(); let value_map = rule.countdata.entry(key).or_default(); value_map.push(AggRecordTimeInfo { - field_record_value: field_value, - record_time: record_time_value, - record_event_id: event_id, + field_value, + time, + event_id, + computer, + channel, }); } @@ -197,9 +212,11 @@ pub fn aggregation_condition_select( #[derive(Debug, Clone, PartialEq, Eq, Default)] /// countの括弧内の情報とレコードの情報を所持する構造体 pub struct AggRecordTimeInfo { - pub field_record_value: String, - pub record_time: DateTime, - pub record_event_id: String, + pub field_value: String, + pub time: DateTime, + pub event_id: String, + pub computer: String, + pub channel: String, } #[derive(Debug)] @@ -341,7 +358,7 @@ impl CountStrategy for FieldStrategy { return; } - let value = &datas[idx as usize].field_record_value; + let value = &datas[idx as usize].field_value; let key_val = self.value_2_cnt.get_key_value_mut(value); if let Some(kv) = key_val { let (_, val) = kv; @@ -356,7 +373,7 @@ impl CountStrategy for FieldStrategy { return; } - let record_value = &datas[idx as usize].field_record_value; + let record_value = &datas[idx as usize].field_value; let key_val = self.value_2_cnt.get_key_value_mut(record_value); if key_val.is_none() { return; @@ -386,7 +403,7 @@ impl CountStrategy for FieldStrategy { values.len() as i64, key.to_string(), values, - datas.first().unwrap().record_time, + datas.first().unwrap().time, datas.to_vec(), ) } @@ -425,7 +442,7 @@ impl CountStrategy for NoFieldStrategy { cnt, key.to_string(), vec![], - datas.first().unwrap().record_time, + datas.first().unwrap().time, datas.to_vec(), ); self.cnt = 0; //cntを初期化 @@ -445,11 +462,11 @@ fn _create_counter(rule: &RuleNode) -> Box { } fn _get_timestamp(idx: i64, datas: &[AggRecordTimeInfo]) -> i64 { - datas[idx as usize].record_time.timestamp() + datas[idx as usize].time.timestamp() } fn _get_timestamp_subsec_nano(idx: i64, datas: &[AggRecordTimeInfo]) -> u32 { - datas[idx as usize].record_time.timestamp_subsec_nanos() + datas[idx as usize].time.timestamp_subsec_nanos() } // data[left]からdata[right-1]までのデータがtimeframeに収まっているか判定する @@ -479,11 +496,11 @@ pub fn judge_timeframe( // AggRecordTimeInfoを時間順がソートされている前提で処理を進める let mut datas = time_datas.to_owned(); - datas.sort_by(|a, b| a.record_time.cmp(&b.record_time)); + datas.sort_by(|a, b| a.time.cmp(&b.time)); // timeframeの設定がルールにない時は最初と最後の要素の時間差をtimeframeに設定する。 - let def_frame = datas.last().unwrap().record_time.timestamp() - - datas.first().unwrap().record_time.timestamp(); + let def_frame = + datas.last().unwrap().time.timestamp() - datas.first().unwrap().time.timestamp(); let frame = get_sec_timeframe(rule, stored_static).unwrap_or(def_frame); // left <= i < rightの範囲にあるdata[i]がtimeframe内にあるデータであると考える diff --git a/src/detections/rule/mod.rs b/src/detections/rule/mod.rs index c8f17eb7d..17482f8b7 100644 --- a/src/detections/rule/mod.rs +++ b/src/detections/rule/mod.rs @@ -17,7 +17,7 @@ use self::selectionnodes::{LeafSelectionNode, SelectionNode}; mod aggregation_parser; mod condition_parser; pub mod correlation_parser; -mod count; +pub(crate) mod count; mod matchers; mod selectionnodes; From ff283355670ef90e444fa097f920478745d4d0bb Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Tue, 9 Jul 2024 22:42:14 +0900 Subject: [PATCH 04/15] chg: output channel/event_id/computer when agg/correlation result --- src/afterfact.rs | 92 +++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 59 deletions(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index a25403ade..da1639fa5 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -547,68 +547,42 @@ fn calc_statistic_info( .insert(detect_info.ruleid.to_owned()); afterfact_info.unique_detect_counts_by_level[level_suffix] += 1; } - match &detect_info.agg_result { - None => { - update_afterfact_aggregations( - detect_info, - &detect_info.computername, - afterfact_info, - output_option, - ); - } - Some(agg_result) => { - for a in agg_result.agg_record_time_info.iter() { - update_afterfact_aggregations( - detect_info, - &CompactString::from(a.computer.clone()), - afterfact_info, - output_option, - ); - } - } + let computer_rule_check_key = CompactString::from(format!( + "{}|{}", + detect_info.computername, &detect_info.rulepath + )); + if !afterfact_info + .detected_computer_and_rule_names + .contains(&computer_rule_check_key) + { + afterfact_info + .detected_computer_and_rule_names + .insert(computer_rule_check_key); + countup_aggregation( + &mut afterfact_info.detect_counts_by_computer_and_level, + &detect_info.level, + &detect_info.computername, + ); } - } - } -} + afterfact_info.rule_title_path_map.insert( + detect_info.ruletitle.to_owned(), + detect_info.rulepath.to_owned(), + ); -fn update_afterfact_aggregations( - detect_info: &DetectInfo, - computername: &CompactString, - afterfact_info: &mut AfterfactInfo, - output_option: &OutputOption, -) { - let computer_rule_check_key = - CompactString::from(format!("{}|{}", computername, &detect_info.rulepath)); - if !afterfact_info - .detected_computer_and_rule_names - .contains(&computer_rule_check_key) - { - afterfact_info - .detected_computer_and_rule_names - .insert(computer_rule_check_key); - countup_aggregation( - &mut afterfact_info.detect_counts_by_computer_and_level, - &detect_info.level, - computername, - ); + countup_aggregation( + &mut afterfact_info.detect_counts_by_date_and_level, + &detect_info.level, + &format_time(&detect_info.detected_time, true, output_option), + ); + countup_aggregation( + &mut afterfact_info.detect_counts_by_rule_and_level, + &detect_info.level, + &detect_info.ruletitle, + ); + let level_suffix = get_level_suffix(detect_info.level.as_str()); + afterfact_info.total_detect_counts_by_level[level_suffix] += 1; + } } - afterfact_info.rule_title_path_map.insert( - detect_info.ruletitle.to_owned(), - detect_info.rulepath.to_owned(), - ); - - countup_aggregation( - &mut afterfact_info.detect_counts_by_date_and_level, - &detect_info.level, - &format_time(&detect_info.detected_time, true, output_option), - ); - countup_aggregation( - &mut afterfact_info.detect_counts_by_rule_and_level, - &detect_info.level, - &detect_info.ruletitle, - ); - let level_suffix = get_level_suffix(detect_info.level.as_str()); - afterfact_info.total_detect_counts_by_level[level_suffix] += 1; } pub fn output_additional_afterfact( From 932674d29e2f1f0b7efcfbbbf9c83439d5e4202a Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Tue, 9 Jul 2024 22:55:25 +0900 Subject: [PATCH 05/15] chg: output channel/event_id/computer when agg/correlation result --- src/detections/rule/count.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index de5d5959c..2da437d28 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -69,7 +69,7 @@ pub fn countup( STORED_EKEY_ALIAS.read().unwrap().as_ref().unwrap(), ) .unwrap(); - let event_id = event_id.to_string(); + let event_id = event_id.to_string().trim_matches('\"').to_string(); let computer = utils::get_event_value( "Event.System.Computer", record, From 23fe40108132f9e1206ea2a5748dde64c3f45c25 Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Tue, 9 Jul 2024 23:01:06 +0900 Subject: [PATCH 06/15] chg: sort computer/event_id/channel multiple val --- src/detections/detection.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index bcebb50c5..460159633 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -800,6 +800,7 @@ impl Detection { .iter() .cloned() .collect::>() + .iter().sorted() .join(" ¦ ") .into(), ), @@ -817,6 +818,7 @@ impl Detection { .iter() .cloned() .collect::>() + .iter().sorted() .join(" ¦ ") .into(), ), @@ -844,6 +846,7 @@ impl Detection { .iter() .cloned() .collect::>() + .iter().sorted() .join(" ¦ ") .into(), ), From c55e3e94fa44cb550a86c4b96c06703d933196df Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Tue, 9 Jul 2024 23:02:25 +0900 Subject: [PATCH 07/15] chg: sort computer/event_id/channel multiple val --- src/detections/detection.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 460159633..c4966064d 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -800,7 +800,8 @@ impl Detection { .iter() .cloned() .collect::>() - .iter().sorted() + .iter() + .sorted() .join(" ¦ ") .into(), ), @@ -818,7 +819,8 @@ impl Detection { .iter() .cloned() .collect::>() - .iter().sorted() + .iter() + .sorted() .join(" ¦ ") .into(), ), @@ -846,7 +848,8 @@ impl Detection { .iter() .cloned() .collect::>() - .iter().sorted() + .iter() + .sorted() .join(" ¦ ") .into(), ), From d1ea60e6fc5e3b471a257ae496ce4ca0c6ef5ad2 Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Wed, 10 Jul 2024 08:34:01 +0900 Subject: [PATCH 08/15] refactor: remove duplicated code --- src/detections/detection.rs | 67 +++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index c4966064d..90ced8ca4 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -22,6 +22,7 @@ use crate::detections::configs::STORED_EKEY_ALIAS; use crate::detections::field_data_map::FieldDataMapKey; use crate::detections::message::{AlertMessage, DetectInfo, ERROR_LOG_STACK, TAGS_CONFIG}; use crate::detections::rule::correlation_parser::parse_correlation_rules; +use crate::detections::rule::count::AggRecordTimeInfo; use crate::detections::rule::{self, AggResult, RuleNode}; use crate::detections::utils::{create_recordinfos, format_time, write_color_buffer}; use crate::detections::utils::{get_serde_number_to_string, make_ascii_titlecase}; @@ -792,18 +793,10 @@ impl Detection { profile_converter.insert( key.as_str(), Computer( - agg_result - .agg_record_time_info - .iter() - .map(|x| x.computer.clone()) - .collect::>() // HashSetに変換して重複を削除 - .iter() - .cloned() - .collect::>() - .iter() - .sorted() - .join(" ¦ ") - .into(), + Detection::join_agg_values(&agg_result.agg_record_time_info, |x| { + x.computer.clone() + }) + .into(), ), ); } @@ -811,18 +804,10 @@ impl Detection { profile_converter.insert( key.as_str(), Channel( - agg_result - .agg_record_time_info - .iter() - .map(|x| x.channel.clone()) - .collect::>() // HashSetに変換して重複を削除 - .iter() - .cloned() - .collect::>() - .iter() - .sorted() - .join(" ¦ ") - .into(), + Detection::join_agg_values(&agg_result.agg_record_time_info, |x| { + x.channel.clone() + }) + .into(), ), ); } @@ -840,18 +825,10 @@ impl Detection { profile_converter.insert( key.as_str(), EventID( - agg_result - .agg_record_time_info - .iter() - .map(|x| x.event_id.clone()) - .collect::>() // HashSetに変換して重複を削除 - .iter() - .cloned() - .collect::>() - .iter() - .sorted() - .join(" ¦ ") - .into(), + Detection::join_agg_values(&agg_result.agg_record_time_info, |x| { + x.event_id.clone() + }) + .into(), ), ); } @@ -1032,6 +1009,24 @@ impl Detection { detect_info } + fn join_agg_values( + agg_record_time_infos: &[AggRecordTimeInfo], + extractor: F, + ) -> CompactString + where + F: Fn(&AggRecordTimeInfo) -> String, + { + agg_record_time_infos + .iter() + .map(&extractor) + .collect::>() // Convert to HashSet to remove duplicates + .into_iter() + .collect::>() // Convert back to Vec to sort + .iter() + .sorted() + .join(" ¦ ") + .into() // Convert to CompactString + } /// rule内のtagsの内容を配列として返却する関数 fn get_tag_info(rule: &RuleNode) -> Nested { Nested::from_iter( From e0a90a580e38760937dc8e7ecac7488af2de4d86 Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:33:12 +0900 Subject: [PATCH 09/15] chg: output evtx_file_path when agg/correlation rule --- src/detections/detection.rs | 14 ++++++++++---- src/detections/rule/count.rs | 18 +++++++++++------- src/detections/rule/mod.rs | 2 +- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 90ced8ca4..81274885e 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -858,7 +858,15 @@ impl Detection { profile_converter.insert(key.as_str(), RuleFile(rule_path.into())); } EvtxFile(_) => { - profile_converter.insert(key.as_str(), EvtxFile("-".into())); + profile_converter.insert( + key.as_str(), + EvtxFile( + Detection::join_agg_values(&agg_result.agg_record_time_info, |x| { + x.evtx_file_path.clone() + }) + .into(), + ), + ); } MitreTactics(_) => { let tactics = tag_info @@ -1021,11 +1029,9 @@ impl Detection { .map(&extractor) .collect::>() // Convert to HashSet to remove duplicates .into_iter() - .collect::>() // Convert back to Vec to sort - .iter() .sorted() .join(" ¦ ") - .into() // Convert to CompactString + .into() } /// rule内のtagsの内容を配列として返却する関数 fn get_tag_info(rule: &RuleNode) -> Nested { diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index 2da437d28..c7278c85f 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -1,9 +1,11 @@ use crate::detections::configs::EventKeyAliasConfig; use crate::detections::configs::StoredStatic; use crate::detections::configs::STORED_EKEY_ALIAS; +use crate::detections::detection::EvtxRecordInfo; use crate::detections::message; use crate::detections::message::AlertMessage; use crate::detections::message::ERROR_LOG_STACK; +use crate::detections::rule::aggregation_parser::AggregationConditionToken; use crate::detections::rule::AggResult; use crate::detections::rule::RuleNode; use chrono::{DateTime, TimeZone, Utc}; @@ -12,21 +14,19 @@ use serde_json::Value; use std::num::ParseIntError; use std::path::Path; -use crate::detections::rule::aggregation_parser::AggregationConditionToken; - use crate::detections::utils; /// 検知された際にカウント情報を投入する関数 pub fn count( rule: &mut RuleNode, - record: &Value, + evtx_rec: &EvtxRecordInfo, verbose_flag: bool, quiet_errors_flag: bool, json_input_flag: bool, ) { let key: String = create_count_key( rule, - record, + &evtx_rec.record, verbose_flag, quiet_errors_flag, STORED_EKEY_ALIAS.read().unwrap().as_ref().unwrap(), @@ -43,14 +43,14 @@ pub fn count( let field_value = get_alias_value_in_record( rule, field_name, - record, + &evtx_rec.record, false, verbose_flag, quiet_errors_flag, STORED_EKEY_ALIAS.read().unwrap().as_ref().unwrap(), ) .unwrap_or_default(); - countup(rule, key, field_value, record, json_input_flag); + countup(rule, key, field_value, evtx_rec, json_input_flag); } ///count byの条件に合致する検知済みレコードの数を増やすための関数 @@ -58,9 +58,10 @@ pub fn countup( rule: &mut RuleNode, key: String, field_value: String, - record: &Value, + evtx_rec: &EvtxRecordInfo, json_input_flag: bool, ) { + let record = &evtx_rec.record; let default_time = Utc.with_ymd_and_hms(1977, 1, 1, 0, 0, 0).unwrap(); let time = message::get_event_time(record, json_input_flag).unwrap_or(default_time); let event_id = utils::get_event_value( @@ -84,6 +85,7 @@ pub fn countup( ) .unwrap(); let channel = channel.to_string().trim_matches('\"').to_string(); + let evtx_file_path = evtx_rec.evtx_filepath.to_string(); let value_map = rule.countdata.entry(key).or_default(); value_map.push(AggRecordTimeInfo { field_value, @@ -91,6 +93,7 @@ pub fn countup( event_id, computer, channel, + evtx_file_path, }); } @@ -217,6 +220,7 @@ pub struct AggRecordTimeInfo { pub event_id: String, pub computer: String, pub channel: String, + pub evtx_file_path: String, } #[derive(Debug)] diff --git a/src/detections/rule/mod.rs b/src/detections/rule/mod.rs index 17482f8b7..f8cfea3ff 100644 --- a/src/detections/rule/mod.rs +++ b/src/detections/rule/mod.rs @@ -94,7 +94,7 @@ impl RuleNode { if result && self.has_agg_condition() { count::count( self, - &event_record.record, + event_record, verbose_flag, quiet_errors_flag, json_input_flag, From a8f9236ce5d444a7b412a3a3c2818a70dd7c72a1 Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Wed, 10 Jul 2024 21:40:20 +0900 Subject: [PATCH 10/15] fix: Top 5 computers with most unique detections's output --- src/afterfact.rs | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index da1639fa5..9afbbe688 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -547,22 +547,32 @@ fn calc_statistic_info( .insert(detect_info.ruleid.to_owned()); afterfact_info.unique_detect_counts_by_level[level_suffix] += 1; } - let computer_rule_check_key = CompactString::from(format!( - "{}|{}", - detect_info.computername, &detect_info.rulepath - )); - if !afterfact_info - .detected_computer_and_rule_names - .contains(&computer_rule_check_key) - { - afterfact_info + let computer_names = match &detect_info.agg_result { + None => vec![detect_info.computername.clone()], + Some(agg) => agg.agg_record_time_info.iter().map(|a| CompactString::from(a.computer.clone())) .collect::>() // Convert to HashSet to remove duplicates + .into_iter() + .sorted() + .collect() + }; + for computername in &computer_names { + let computer_rule_check_key = CompactString::from(format!( + "{}|{}", + computername, &detect_info.rulepath + )); + println!("{:?}", computer_rule_check_key); + if !afterfact_info .detected_computer_and_rule_names - .insert(computer_rule_check_key); - countup_aggregation( - &mut afterfact_info.detect_counts_by_computer_and_level, - &detect_info.level, - &detect_info.computername, - ); + .contains(&computer_rule_check_key) + { + afterfact_info + .detected_computer_and_rule_names + .insert(computer_rule_check_key); + countup_aggregation( + &mut afterfact_info.detect_counts_by_computer_and_level, + &detect_info.level, + computername, + ); + } } afterfact_info.rule_title_path_map.insert( detect_info.ruletitle.to_owned(), From 80d219d97517ac6c097cfe96c32670757b56dc16 Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Wed, 10 Jul 2024 21:41:47 +0900 Subject: [PATCH 11/15] fix: Top 5 computers with most unique detections's output --- src/afterfact.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index 9afbbe688..321afec26 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -549,16 +549,18 @@ fn calc_statistic_info( } let computer_names = match &detect_info.agg_result { None => vec![detect_info.computername.clone()], - Some(agg) => agg.agg_record_time_info.iter().map(|a| CompactString::from(a.computer.clone())) .collect::>() // Convert to HashSet to remove duplicates + Some(agg) => agg + .agg_record_time_info + .iter() + .map(|a| CompactString::from(a.computer.clone())) + .collect::>() // Convert to HashSet to remove duplicates .into_iter() .sorted() - .collect() + .collect(), }; for computername in &computer_names { - let computer_rule_check_key = CompactString::from(format!( - "{}|{}", - computername, &detect_info.rulepath - )); + let computer_rule_check_key = + CompactString::from(format!("{}|{}", computername, &detect_info.rulepath)); println!("{:?}", computer_rule_check_key); if !afterfact_info .detected_computer_and_rule_names From d69134afba52803b803e49091f632eb9da36a577 Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:16:38 +0900 Subject: [PATCH 12/15] fix: remove debug print --- src/afterfact.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index 321afec26..37541b5ea 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -561,7 +561,6 @@ fn calc_statistic_info( for computername in &computer_names { let computer_rule_check_key = CompactString::from(format!("{}|{}", computername, &detect_info.rulepath)); - println!("{:?}", computer_rule_check_key); if !afterfact_info .detected_computer_and_rule_names .contains(&computer_rule_check_key) From b6415172197ef8281bcc9508b16c3ab90748224f Mon Sep 17 00:00:00 2001 From: Yamato Security <71482215+YamatoSecurity@users.noreply.github.com> Date: Sun, 14 Jul 2024 15:29:15 +0900 Subject: [PATCH 13/15] update changelog --- CHANGELOG-Japanese.md | 5 +++++ CHANGELOG.md | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index d878456d4..e210c2bc7 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -12,6 +12,11 @@ - `Data`フィールドは、すべて`Data`フィールドとして、またはJSONの配列としてではなく、インデックス化された文字列として表示されるようになった。(#1371) (@fukusuket) - 前: `"Data": ["17514", "Multiprocessor Free", "Service Pack 1"]` - 後: `"Data[3]": "17514", "Data[4]": "Multiprocessor Free", "Data[5]": "Service Pack 1"` +- 集計ルールのアラートに、複数の結果がある場合でも`Channel`と`EventID`の情報が表示されるようにした。 (#1342) (@fukusuket) + +**バグ修正:** +- Sigmaの相関ルールのカウントが`Events with hits`に表示されていなかった。(#1373) (@fukusuket) +- 集計ルールのカウントが`Events with hits`に表示されていなかった。(#1375) (@fukusuket) ## 2.16.0 [2024/06/11] diff --git a/CHANGELOG.md b/CHANGELOG.md index 9de2b80d5..a62764ee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ - `Data` fields are now displayed as indexed strings instead of as all `Data` fields or in an array for JSON. (#1371) (@fukusuket) - Before: `"Data": ["17514", "Multiprocessor Free", "Service Pack 1"]` - After: `"Data[3]": "17514", "Data[4]": "Multiprocessor Free", "Data[5]": "Service Pack 1"` +- Aggregation rule alerts now show `Channel` and `EventID` information even when there are multiple results. (#1342) (@fukusuket) + +**Bug Fixes:** +- Sigma correlation rule count was not showing up in `Events with hits`. (#1373) (@fukusuket) +- Aggregation condition rule count was not showing up in `Events with hits`. (#1375) (@fukusuket) ## 2.16.0 [2024/06/11] From 11dffd172f92ce96a2f68e4e341d67774dab11de Mon Sep 17 00:00:00 2001 From: Yamato Security <71482215+YamatoSecurity@users.noreply.github.com> Date: Sun, 14 Jul 2024 15:29:20 +0900 Subject: [PATCH 14/15] bump --- Cargo.lock | 156 ++++++++++++++++++++++++++--------------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 873663fff..bd8e7f5b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,9 +209,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "bytesize" @@ -252,18 +252,18 @@ dependencies = [ [[package]] name = "castaway" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" dependencies = [ "rustversion", ] [[package]] name = "cc" -version = "1.0.104" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" +checksum = "18e2d530f35b40a84124146478cd16f34225306a8441998836466a2e2961c950" dependencies = [ "jobserver", "libc", @@ -288,7 +288,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -325,9 +325,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", "clap_derive", @@ -335,9 +335,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstream", "anstyle", @@ -354,7 +354,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -831,7 +831,7 @@ dependencies = [ "bytesize", "chrono", "cidr-utils", - "clap 4.5.8", + "clap 4.5.9", "comfy-table", "compact_str", "console", @@ -1072,7 +1072,7 @@ checksum = "313560d2dd5dcabbc1a9690c88e1f443136d6025ca8a421df2d5719f45357979" dependencies = [ "anyhow", "chrono", - "clap 4.5.8", + "clap 4.5.9", "file-chunker", "memmap2 0.9.4", "num_cpus", @@ -1392,7 +1392,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -1449,7 +1449,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -1504,9 +1504,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e446ed58cef1bbfe847bc2fda0e2e4ea9f0e57b90c507d4781292590d72a4e" +checksum = "4091e032efecb09d7b1f711f487b85ab925632a842627e3200fb088382cde32c" dependencies = [ "memchr", ] @@ -1645,9 +1645,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19549741604902eb99a7ed0ee177a0663ee1eda51a29f71401f166e47e77806a" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -1656,22 +1656,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9f96e283ec64401f30d3df8ee2aaeb2561f34c824381efa24a35f79bf40ee4" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.68", + "syn 2.0.71", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c74a686185620830701348de757fd36bef4aa9680fd23c49fc539ddcc1af32" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" dependencies = [ "globset", "sha2", @@ -1699,11 +1699,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.4" +version = "0.23.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" dependencies = [ "log", + "once_cell", "ring", "rustls-pki-types", "rustls-webpki", @@ -1719,9 +1720,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" dependencies = [ "ring", "rustls-pki-types", @@ -1766,22 +1767,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -1892,7 +1893,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -1914,9 +1915,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", @@ -1962,29 +1963,29 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] name = "tinyvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -2022,7 +2023,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] @@ -2075,9 +2076,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.7" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11a831e3c0b56e438a28308e7c810799e3c118417f342d30ecec080105395cd" +checksum = "72139d247e5f97a3eff96229a7ae85ead5328a39efe76f8bf5a06313d505b6ea" dependencies = [ "base64", "flate2", @@ -2085,7 +2086,6 @@ dependencies = [ "once_cell", "rustls", "rustls-pki-types", - "rustls-webpki", "url", "webpki-roots", ] @@ -2156,7 +2156,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", "wasm-bindgen-shared", ] @@ -2178,7 +2178,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2241,7 +2241,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2259,7 +2259,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2279,18 +2279,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -2301,9 +2301,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -2313,9 +2313,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -2325,15 +2325,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -2343,9 +2343,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -2355,9 +2355,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -2367,9 +2367,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -2379,9 +2379,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winstructs" @@ -2426,7 +2426,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.71", ] [[package]] From 62454b9f6104e188b0de2687c1af16f7e13833be Mon Sep 17 00:00:00 2001 From: fukusuket <41001169+fukusuket@users.noreply.github.com> Date: Sun, 14 Jul 2024 20:50:55 +0900 Subject: [PATCH 15/15] fix: channel abbreviation --- src/detections/detection.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 81274885e..a385936c8 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -805,7 +805,14 @@ impl Detection { key.as_str(), Channel( Detection::join_agg_values(&agg_result.agg_record_time_info, |x| { - x.channel.clone() + stored_static.disp_abbr_generic.replace_all( + stored_static + .ch_config + .get(&CompactString::from(&x.channel.to_ascii_lowercase())) + .unwrap_or(&CompactString::from(&x.channel)) + .as_str(), + &stored_static.disp_abbr_general_values, + ) }) .into(), ),