added mitre attack data output in csv output (#397)

* added tags information in csv output #234

* fixed test due to change csvformat struct #234

* changed tag info separator #234

* changed separator #234

* changed tag info separator #234
This commit is contained in:
DustInDark
2022-02-15 02:13:37 +09:00
committed by GitHub
parent df86958850
commit 19c44b4f66
3 changed files with 53 additions and 21 deletions

View File

@@ -23,6 +23,7 @@ pub struct CsvFormat<'a> {
level: &'a str, level: &'a str,
rule_title: &'a str, rule_title: &'a str,
details: &'a str, details: &'a str,
mitre_attack: &'a str,
rule_path: &'a str, rule_path: &'a str,
file_path: &'a str, file_path: &'a str,
} }
@@ -213,6 +214,7 @@ fn emit_csv<W: std::io::Write>(
event_i_d: &detect_info.eventid, event_i_d: &detect_info.eventid,
rule_title: &detect_info.alert, rule_title: &detect_info.alert,
details: &detect_info.detail, details: &detect_info.detail,
mitre_attack: &detect_info.tag_info,
})?; })?;
} }
let level_suffix = *configs::LEVELMAP let level_suffix = *configs::LEVELMAP
@@ -350,6 +352,7 @@ mod tests {
let test_computername = "testcomputer"; let test_computername = "testcomputer";
let test_eventid = "1111"; let test_eventid = "1111";
let output = "pokepoke"; let output = "pokepoke";
let test_attack = "execution/txxxx.yyy";
{ {
let mut messages = print::MESSAGES.lock().unwrap(); let mut messages = print::MESSAGES.lock().unwrap();
messages.clear(); messages.clear();
@@ -377,13 +380,15 @@ mod tests {
test_eventid.to_string(), test_eventid.to_string(),
test_title.to_string(), test_title.to_string(),
output.to_string(), output.to_string(),
test_attack.to_string(),
); );
} }
let expect_time = Utc let expect_time = Utc
.datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ")
.unwrap(); .unwrap();
let expect_tz = expect_time.with_timezone(&Local); let expect_tz = expect_time.with_timezone(&Local);
let expect = "Timestamp,Computer,EventID,Level,RuleTitle,Details,RulePath,FilePath\n" let expect =
"Timestamp,Computer,EventID,Level,RuleTitle,Details,MitreAttack,RulePath,FilePath\n"
.to_string() .to_string()
+ &expect_tz + &expect_tz
.clone() .clone()
@@ -400,6 +405,8 @@ mod tests {
+ "," + ","
+ output + output
+ "," + ","
+ test_attack
+ ","
+ testrulepath + testrulepath
+ "," + ","
+ &testfilepath.to_string() + &testfilepath.to_string()
@@ -425,6 +432,7 @@ mod tests {
let test_computername = "testcomputer2"; let test_computername = "testcomputer2";
let test_eventid = "2222"; let test_eventid = "2222";
let output = "displaytest"; let output = "displaytest";
let test_attack = "execution/txxxx.zzz";
{ {
let mut messages = print::MESSAGES.lock().unwrap(); let mut messages = print::MESSAGES.lock().unwrap();
messages.clear(); messages.clear();
@@ -452,6 +460,7 @@ mod tests {
test_eventid.to_string(), test_eventid.to_string(),
test_title.to_string(), test_title.to_string(),
output.to_string(), output.to_string(),
test_attack.to_string(),
); );
messages.debug(); messages.debug();
} }

View File

@@ -190,6 +190,12 @@ impl Detection {
/// 条件に合致したレコードを表示するための関数 /// 条件に合致したレコードを表示するための関数
fn insert_message(rule: &RuleNode, record_info: &EvtxRecordInfo) { fn insert_message(rule: &RuleNode, record_info: &EvtxRecordInfo) {
let tag_info: Vec<String> = rule.yaml["tags"]
.as_vec()
.unwrap_or(&Vec::default())
.into_iter()
.map(|info| info.as_str().unwrap_or("").replace("attack.", ""))
.collect();
MESSAGES.lock().unwrap().insert( MESSAGES.lock().unwrap().insert(
record_info.evtx_filepath.to_string(), record_info.evtx_filepath.to_string(),
rule.rulepath.to_string(), rule.rulepath.to_string(),
@@ -203,11 +209,18 @@ impl Detection {
.to_string(), .to_string(),
rule.yaml["title"].as_str().unwrap_or("").to_string(), rule.yaml["title"].as_str().unwrap_or("").to_string(),
rule.yaml["details"].as_str().unwrap_or("").to_string(), rule.yaml["details"].as_str().unwrap_or("").to_string(),
tag_info.join(" : "),
); );
} }
/// insert aggregation condition detection message to output stack /// insert aggregation condition detection message to output stack
fn insert_agg_message(rule: &RuleNode, agg_result: AggResult) { fn insert_agg_message(rule: &RuleNode, agg_result: AggResult) {
let tag_info: Vec<String> = rule.yaml["tags"]
.as_vec()
.unwrap_or(&Vec::default())
.into_iter()
.map(|info| info.as_str().unwrap_or("").replace("attack.", ""))
.collect();
let output = Detection::create_count_output(rule, &agg_result); let output = Detection::create_count_output(rule, &agg_result);
MESSAGES.lock().unwrap().insert_message( MESSAGES.lock().unwrap().insert_message(
"-".to_owned(), "-".to_owned(),
@@ -218,6 +231,7 @@ impl Detection {
"-".to_owned(), "-".to_owned(),
rule.yaml["title"].as_str().unwrap_or("").to_owned(), rule.yaml["title"].as_str().unwrap_or("").to_owned(),
output.to_owned(), output.to_owned(),
tag_info.join(" : "),
) )
} }

View File

@@ -30,6 +30,7 @@ pub struct DetectInfo {
pub eventid: String, pub eventid: String,
pub alert: String, pub alert: String,
pub detail: String, pub detail: String,
pub tag_info: String,
} }
pub struct AlertMessage {} pub struct AlertMessage {}
@@ -71,6 +72,7 @@ impl Message {
eventid: String, eventid: String,
event_title: String, event_title: String,
event_detail: String, event_detail: String,
tag_info: String,
) { ) {
let detect_info = DetectInfo { let detect_info = DetectInfo {
filepath: target_file, filepath: target_file,
@@ -80,6 +82,7 @@ impl Message {
eventid: eventid, eventid: eventid,
alert: event_title, alert: event_title,
detail: event_detail, detail: event_detail,
tag_info: tag_info,
}; };
match self.map.get_mut(&event_time) { match self.map.get_mut(&event_time) {
@@ -104,6 +107,7 @@ impl Message {
eventid: String, eventid: String,
event_title: String, event_title: String,
output: String, output: String,
tag_info: String,
) { ) {
let message = &self.parse_message(event_record, output); let message = &self.parse_message(event_record, output);
let default_time = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0); let default_time = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);
@@ -117,6 +121,7 @@ impl Message {
eventid, eventid,
event_title, event_title,
message.to_string(), message.to_string(),
tag_info,
) )
} }
@@ -279,6 +284,7 @@ mod tests {
"1".to_string(), "1".to_string(),
"test1".to_string(), "test1".to_string(),
"CommandLine1: %CommandLine%".to_string(), "CommandLine1: %CommandLine%".to_string(),
"txxx.001".to_string(),
); );
let json_str_2 = r##" let json_str_2 = r##"
@@ -305,6 +311,7 @@ mod tests {
"2".to_string(), "2".to_string(),
"test2".to_string(), "test2".to_string(),
"CommandLine2: %CommandLine%".to_string(), "CommandLine2: %CommandLine%".to_string(),
"txxx.002".to_string(),
); );
let json_str_3 = r##" let json_str_3 = r##"
@@ -331,6 +338,7 @@ mod tests {
"3".to_string(), "3".to_string(),
"test3".to_string(), "test3".to_string(),
"CommandLine3: %CommandLine%".to_string(), "CommandLine3: %CommandLine%".to_string(),
"txxx.003".to_string(),
); );
let json_str_4 = r##" let json_str_4 = r##"
@@ -352,11 +360,12 @@ mod tests {
"4".to_string(), "4".to_string(),
"test4".to_string(), "test4".to_string(),
"CommandLine4: %CommandLine%".to_string(), "CommandLine4: %CommandLine%".to_string(),
"txxx.004".to_string(),
); );
let display = format!("{}", format_args!("{:?}", message)); let display = format!("{}", format_args!("{:?}", message));
println!("display::::{}", display); println!("display::::{}", display);
let expect = "Message { map: {1970-01-01T00:00:00Z: [DetectInfo { filepath: \"a\", rulepath: \"test_rule4\", level: \"medium\", computername: \"testcomputer4\", eventid: \"4\", alert: \"test4\", detail: \"CommandLine4: hoge\" }], 1996-02-27T01:05:01Z: [DetectInfo { filepath: \"a\", rulepath: \"test_rule\", level: \"high\", computername: \"testcomputer1\", eventid: \"1\", alert: \"test1\", detail: \"CommandLine1: hoge\" }, DetectInfo { filepath: \"a\", rulepath: \"test_rule2\", level: \"high\", computername: \"testcomputer2\", eventid: \"2\", alert: \"test2\", detail: \"CommandLine2: hoge\" }], 2000-01-21T09:06:01Z: [DetectInfo { filepath: \"a\", rulepath: \"test_rule3\", level: \"high\", computername: \"testcomputer3\", eventid: \"3\", alert: \"test3\", detail: \"CommandLine3: hoge\" }]} }"; let expect = "Message { map: {1970-01-01T00:00:00Z: [DetectInfo { filepath: \"a\", rulepath: \"test_rule4\", level: \"medium\", computername: \"testcomputer4\", eventid: \"4\", alert: \"test4\", detail: \"CommandLine4: hoge\", tag_info: \"txxx.004\" }], 1996-02-27T01:05:01Z: [DetectInfo { filepath: \"a\", rulepath: \"test_rule\", level: \"high\", computername: \"testcomputer1\", eventid: \"1\", alert: \"test1\", detail: \"CommandLine1: hoge\", tag_info: \"txxx.001\" }, DetectInfo { filepath: \"a\", rulepath: \"test_rule2\", level: \"high\", computername: \"testcomputer2\", eventid: \"2\", alert: \"test2\", detail: \"CommandLine2: hoge\", tag_info: \"txxx.002\" }], 2000-01-21T09:06:01Z: [DetectInfo { filepath: \"a\", rulepath: \"test_rule3\", level: \"high\", computername: \"testcomputer3\", eventid: \"3\", alert: \"test3\", detail: \"CommandLine3: hoge\", tag_info: \"txxx.003\" }]} }";
assert_eq!(display, expect); assert_eq!(display, expect);
} }