diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index a1a577fa..19854b5c 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -8,6 +8,7 @@ - `--all-tags`オプションでルールにある全てのtagsを、outputで指定したcsvのMitreAttackの列に出力するようにした。 (#525) (@hitenkoku) - `-R` / `--display-record-id` オプションの追加。evtx file内のレコードを特定するレコードID``が出力できるようになった。 (#548) (@hitenkoku) - レベルごとの検知数が最も多い日を表示するようにした。 (#550) (@hitenkoku) +- レベルごとの検知数上位3つのコンピュータ名を表示するようにした。 (#557)(@hitenkoku) **改善:** diff --git a/CHANGELOG.md b/CHANGELOG.md index 922451c3..26fc99fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ - Added Event Frequency Timeline feature to visualize the number of events. (Note: There needs to be more than 5 events.) (#533)(@hitenkoku) - Display all the `tags` defined in a rule to the `MitreAttack` column when saving to CSV file with the `--all-tags` option. (#525) (@hitenkoku) - Added the `-R / --display-record-id` option: Display the event record ID (``). (#548) (@hitenkoku) -- Display date with most detections by level. (#550) (@hitenkoku) +- Display dates with most detections. (#550) (@hitenkoku) +- Display the top 5 computers with the most unique detections. (#557) (@hitenkoku) **Enhancements:** diff --git a/README-Japanese.md b/README-Japanese.md index 6de603b1..bcef2b8c 100644 --- a/README-Japanese.md +++ b/README-Japanese.md @@ -66,7 +66,8 @@ Hayabusaは、日本の[Yamato Security](https://yamatosecurity.connpass.com/) - [プログレスバー](#プログレスバー) - [標準出力へのカラー設定](#標準出力へのカラー設定) - [イベント頻度タイムライン](#イベント頻度タイムライン) - - [各レベルの最多検知日の出力](#各レベルの最多検知日の出力) + - [最多検知日の出力](#最多検知日の出力) + - [最多検知端末名の出力](#最多検知端末名の出力) - [Hayabusaルール](#hayabusaルール) - [Hayabusa v.s. 変換されたSigmaルール](#hayabusa-vs-変換されたsigmaルール) - [検知ルールのチューニング](#検知ルールのチューニング) @@ -87,7 +88,7 @@ Hayabusaは、日本の[Yamato Security](https://yamatosecurity.connpass.com/) ### スレット(脅威)ハンティング -Hayabusaには現在、2200以上のSigmaルールと約125のHayabusa検知ルールがあり、定期的にルールが追加されています。 最終的な目標はインシデントレスポンスや定期的なスレットハンティングのために、HayabusaエージェントをすべてのWindows端末にインストールして、中央サーバーにアラートを返す仕組みを作ることです。 +Hayabusaには現在、2300以上のSigmaルールと130以上のHayabusa検知ルールがあり、定期的にルールが追加されています。 最終的な目標はインシデントレスポンスや定期的なスレットハンティングのために、HayabusaエージェントをすべてのWindows端末にインストールして、中央サーバーにアラートを返す仕組みを作ることです。 ### フォレンジックタイムラインの高速生成 @@ -155,7 +156,7 @@ CSVのタイムラインをElastic Stackにインポートする方法は[こち * 不良ルールやノイズの多いルールを除外するルールチューニング設定が可能です。 * MITRE ATT&CKとのマッピング (CSVの出力ファイルのみ)。 * ルールレベルのチューニング。 -* イベントログから不審なユーザやファイルを素早く特定するのに有用な、ピボットキーワードの一覧作成。 +* イベントログから不審なユーザやファイルを素早く特定するためのピボットキーワードの一覧作成。 * 詳細な調査のために全フィールド情報の出力。 * 成功と失敗したユーザログオンの要約。 @@ -453,7 +454,7 @@ Checking target evtx FilePath: "./hayabusa-sample-evtx/YamatoSecurity/T1218.004_ ## ピボットキーワードの作成 `-p`もしくは`--pivot-keywords-list`オプションを使うことで不審なユーザやホスト名、プロセスなどを一覧で出力することができ、イベントログから素早く特定することができます。 -ピボットキーワードのカスタマイズは`config/pivot_keywords.txt`を変更することで行うことができます。以下はデフォルトの設定になります。: +ピボットキーワードのカスタマイズは`config/pivot_keywords.txt`を変更することで行うことができます。以下はデフォルトの設定になります: ``` Users.SubjectUserName @@ -577,10 +578,14 @@ Hayabusaの結果は`level`毎に文字色が変わります。 検知したイベントの数が5以上の時、頻度のタイムライン(スパークライン)を画面に出力します。 マーカーの数は最大10個です。 -## 各レベルの最多検知日の出力 +## 最多検知日の出力 各レベルで最も検知された日付を画面に出力します。 +## 最多検知端末名の出力 + +各レベルで多く検知されたユニークなイベントが多い端末名上位5つを画面に出力します。 + # Hayabusaルール Hayabusa検知ルールはSigmaのようなYML形式で記述されています。`rules`ディレクトリに入っていますが、将来的には[https://github.com/Yamato-Security/hayabusa-rules](https://github.com/Yamato-Security/hayabusa-rules)のレポジトリで管理する予定なので、ルールのissueとpull requestはhayabusaのレポジトリではなく、ルールレポジトリへお願いします。 @@ -676,6 +681,7 @@ id,new_level * [LogonTracer](https://github.com/JPCERTCC/LogonTracer) - [JPCERTCC](https://twitter.com/jpcert) による、横方向の動きを検知するためにログオンを視覚化するグラフィカルなインターフェース。 * [RustyBlue](https://github.com/Yamato-Security/RustyBlue) - 大和セキュリティによるDeepBlueCLIのRust版。 * [Sigma](https://github.com/SigmaHQ/Sigma) - コミュニティベースの汎用SIEMルール。 +* [SOF-ELK](https://github.com/philhagen/sof-elk) - [Phil Hagen](https://twitter.com/philhagen) によるDFIR解析用のElastic Stack VM。 * [so-import-evtx](https://docs.securityonion.net/en/2.3/so-import-evtx.html) - evtxファイルをSecurityOnionにインポートするツール。 * [SysmonTools](https://github.com/nshalabi/SysmonTools) - Sysmonの設定とオフライン可視化ツール。 * [Timeline Explorer](https://ericzimmerman.github.io/#!index.md) - [Eric Zimmerman](https://twitter.com/ericrzimmerman) による最高のCSVタイムラインアナライザ。 diff --git a/README.md b/README.md index e5a30cd9..9148bd4e 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,8 @@ Hayabusa is a **Windows event log fast forensics timeline generator** and **thre - [Progress Bar](#progress-bar) - [Color Output](#color-output) - [Event Fequency Timeline](#event-fequency-timeline) - - [Dates with most detections categorized by level](#dates-with-most-detections-categorized-by-level) + - [Dates with most total detections](#dates-with-most-total-detections) + - [Top 5 computers with most unique detections](#top-5-computers-with-most-unique-detections) - [Hayabusa Rules](#hayabusa-rules) - [Hayabusa v.s. Converted Sigma Rules](#hayabusa-vs-converted-sigma-rules) - [Detection Rule Tuning](#detection-rule-tuning) @@ -575,9 +576,13 @@ If you want to disable color output, you can use `--no-color` option. The Event Frequency Timeline feature displays a sparkline frequency timeline of detected events. Note: There needs to be more than 5 events. -## Dates with most detections categorized by level +## Dates with most total detections -A summary of the dates with the most detections categorized by level (`critical`, `high`, etc...). +A summary of the dates with the most total detections categorized by level (`critical`, `high`, etc...). + +## Top 5 computers with most unique detections + +The top 5 computers with the most unique detections categorized by level (`critical`, `high`, etc...). # Hayabusa Rules @@ -675,6 +680,7 @@ There is no "one tool to rule them all" and we have found that each has its own * [LogonTracer](https://github.com/JPCERTCC/LogonTracer) - A graphical interface to visualize logons to detect lateral movement by [JPCERTCC](https://twitter.com/jpcert_en). * [RustyBlue](https://github.com/Yamato-Security/RustyBlue) - Rust port of DeepBlueCLI by Yamato Security. * [Sigma](https://github.com/SigmaHQ/sigma) - Community based generic SIEM rules. +* [SOF-ELK](https://github.com/philhagen/sof-elk) - A pre-packaged VM with Elastic Stack to import data for DFIR analysis by [Phil Hagen](https://twitter.com/philhagen) * [so-import-evtx](https://docs.securityonion.net/en/2.3/so-import-evtx.html) - Import evtx files into Security Onion. * [SysmonTools](https://github.com/nshalabi/SysmonTools) - Configuration and off-line log visualization tool for Sysmon. * [Timeline Explorer](https://ericzimmerman.github.io/#!index.md) - The best CSV timeline analyzer by [Eric Zimmerman](https://twitter.com/ericrzimmerman). diff --git a/rules b/rules index 33126392..902c59e3 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit 3312639216142abe4f4fffb7e28d92ade7cf6ba0 +Subproject commit 902c59e3c557617df1c7bac777db3d72e98a1a00 diff --git a/screenshots/HayabusaResultsSummary.png b/screenshots/HayabusaResultsSummary.png index a8f5afb3..1efd8ec9 100644 Binary files a/screenshots/HayabusaResultsSummary.png and b/screenshots/HayabusaResultsSummary.png differ diff --git a/src/afterfact.rs b/src/afterfact.rs index 6a271127..da9df573 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -202,9 +202,12 @@ fn emit_csv( // level is devided by "Critical","High","Medium","Low","Informational","Undefined". let mut total_detect_counts_by_level: Vec = vec![0; 6]; let mut unique_detect_counts_by_level: Vec = vec![0; 6]; - let mut detected_rule_files: Vec = Vec::new(); + let mut detected_rule_files: HashSet = HashSet::new(); + let mut detected_computer_and_rule_names: HashSet = HashSet::new(); let mut detect_counts_by_date_and_level: HashMap> = HashMap::new(); + let mut detect_counts_by_computer_and_level: HashMap> = + HashMap::new(); let levels = Vec::from([ "critical", @@ -217,6 +220,7 @@ fn emit_csv( // レベル別、日ごとの集計用変数の初期化 for level_init in levels { detect_counts_by_date_and_level.insert(level_init.to_string(), HashMap::new()); + detect_counts_by_computer_and_level.insert(level_init.to_string(), HashMap::new()); } println!(); @@ -300,9 +304,28 @@ fn emit_csv( .entry(time_str_date.to_string()) .or_insert(0) += 1; if !detected_rule_files.contains(&detect_info.rulepath) { - detected_rule_files.push(detect_info.rulepath.clone()); + detected_rule_files.insert(detect_info.rulepath.clone()); unique_detect_counts_by_level[level_suffix] += 1; } + let computer_rule_check_key = + format!("{}|{}", &detect_info.computername, &detect_info.rulepath); + if !detected_computer_and_rule_names.contains(&computer_rule_check_key) { + detected_computer_and_rule_names.insert(computer_rule_check_key); + let mut detect_counts_by_computer = detect_counts_by_computer_and_level + .get(&detect_info.level.to_lowercase()) + .unwrap_or_else(|| { + detect_counts_by_computer_and_level + .get("undefined") + .unwrap() + }) + .clone(); + *detect_counts_by_computer + .entry(Clone::clone(&detect_info.computername)) + .or_insert(0) += 1; + detect_counts_by_computer_and_level + .insert(detect_info.level.to_lowercase(), detect_counts_by_computer); + } + total_detect_counts_by_level[level_suffix] += 1; detect_counts_by_date_and_level .insert(detect_info.level.to_lowercase(), detect_counts_by_date); @@ -336,9 +359,6 @@ fn emit_csv( ); println!(); - _print_detection_summary_by_date(detect_counts_by_date_and_level, &color_map); - - println!(); _print_unique_results( total_detect_counts_by_level, "Total".to_string(), @@ -353,6 +373,13 @@ fn emit_csv( "detections".to_string(), &color_map, ); + println!(); + + _print_detection_summary_by_date(detect_counts_by_date_and_level, &color_map); + println!(); + + _print_detection_summary_by_computer(detect_counts_by_computer_and_level, &color_map); + Ok(()) } @@ -457,18 +484,18 @@ fn _print_detection_summary_by_date( for (date, cnt) in detections_by_day { if cnt > &tmp_cnt { date_str = date.clone(); - max_detect_str = format!("{} (Count: {})", date, cnt); + max_detect_str = format!("{} ({})", date, cnt); tmp_cnt = *cnt; } } wtr.set_color(ColorSpec::new().set_fg(_get_output_color(color_map, level))) .ok(); if date_str == String::default() { - max_detect_str = "-".to_string(); + max_detect_str = "n/a".to_string(); } writeln!( wtr, - "Date with most {} detections: {}", + "Date with most total {} detections: {}", level, &max_detect_str ) .ok(); @@ -476,6 +503,50 @@ fn _print_detection_summary_by_date( buf_wtr.print(&wtr).ok(); } +/// 各レベル毎で最も高い検知数を出した日付を出力する +fn _print_detection_summary_by_computer( + detect_counts_by_computer: HashMap>, + color_map: &HashMap, +) { + let buf_wtr = BufferWriter::stdout(ColorChoice::Always); + let mut wtr = buf_wtr.buffer(); + wtr.set_color(ColorSpec::new().set_fg(None)).ok(); + + let output_levels = Vec::from(["critical", "high", "medium", "low", "informational"]); + + for level in output_levels { + // output_levelsはlevelsからundefinedを除外した配列であり、各要素は必ず初期化されているのでSomeであることが保証されているのでunwrapをそのまま実施 + let detections_by_computer = detect_counts_by_computer.get(level).unwrap(); + let mut result_vec: Vec = Vec::new(); + //computer nameで-となっているものは除外して集計する + let mut sorted_detections: Vec<(&String, &i128)> = detections_by_computer + .iter() + .filter(|a| a.0 != "-") + .collect(); + + sorted_detections.sort_by(|a, b| (-a.1).cmp(&(-b.1))); + + for x in sorted_detections.iter().take(5) { + result_vec.push(format!("{} ({})", x.0, x.1)); + } + let result_str = if result_vec.is_empty() { + "n/a".to_string() + } else { + result_vec.join(", ") + }; + + wtr.set_color(ColorSpec::new().set_fg(_get_output_color(color_map, level))) + .ok(); + writeln!( + wtr, + "Top 5 computers with most unique {} detections: {}", + level, &result_str + ) + .ok(); + } + buf_wtr.print(&wtr).ok(); +} + fn format_time(time: &DateTime) -> String { if configs::CONFIG.read().unwrap().args.is_present("utc") { format_rfc(time)