diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index 58b40561..2c89d72b 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -8,6 +8,9 @@ **改善:** +- EventID解析のオプションをmetricsオプションに変更した。(旧: -s -> 新: -M) (#706) (@hitenkoku) +- ルール更新オプション(`-u`)を利用したときにHayabusaの新バージョンがないかを確認し、表示するようにした。 (#710) (@hitenkoku) + **バグ修正:** ## v1.6.0 [2022/09/16] diff --git a/CHANGELOG.md b/CHANGELOG.md index 7594223c..b7de01be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ **Enhancements:** +- Changed Event ID Statistics option to Event ID Metrics option. (`-s, --statistics` -> `-M, --metrics`) (#706) (@hitenkoku) + (Note: `statistics_event_info.txt` was changed to `event_id_info.txt`.) +- Added display new version of Hayabusa when updating. (#710) (@hitenkoku) + **Bug Fixes:** ## v1.6.0 [2022/09/16] diff --git a/Cargo.lock b/Cargo.lock index f56bd59b..79f40b8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -251,7 +251,7 @@ dependencies = [ "encode_unicode 0.3.6", "libc", "once_cell", - "terminal_size 0.1.17", + "terminal_size", "unicode-width", "winapi", ] @@ -262,6 +262,16 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -508,6 +518,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + [[package]] name = "env_logger" version = "0.7.1" @@ -521,27 +540,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "error-chain" version = "0.12.4" @@ -659,6 +657,18 @@ version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" +[[package]] +name = "futures-io" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" + +[[package]] +name = "futures-sink" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" + [[package]] name = "futures-task" version = "0.3.24" @@ -672,9 +682,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-core", + "futures-io", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -709,6 +722,25 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "h2" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -753,12 +785,13 @@ dependencies = [ "quick-xml", "rand", "regex", + "reqwest", "serde", "serde_derive", "serde_json", "static_vcruntime", "termcolor", - "terminal_size 0.2.1", + "terminal_size", "tokio", "yaml-rust", ] @@ -847,18 +880,33 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", "httpdate", "itoa 1.0.3", "pin-project-lite", + "socket2", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "iana-time-zone" version = "0.1.50" @@ -908,10 +956,10 @@ dependencies = [ ] [[package]] -name = "io-lifetimes" -version = "0.7.3" +name = "ipnet" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ea37f355c05dde75b84bba2d767906ad522e97cd9e2eef2be7a4ab7fb442c06" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "is_elevated" @@ -998,7 +1046,7 @@ dependencies = [ "rayon", "regex", "tempfile", - "terminal_size 0.1.17", + "terminal_size", ] [[package]] @@ -1059,12 +1107,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[package]] -name = "linux-raw-sys" -version = "0.0.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" - [[package]] name = "lock_api" version = "0.4.9" @@ -1108,6 +1150,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + [[package]] name = "miniz_oxide" version = "0.5.4" @@ -1129,6 +1177,24 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -1521,6 +1587,43 @@ dependencies = [ "winapi", ] +[[package]] +name = "reqwest" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "rpmalloc" version = "0.2.2" @@ -1550,20 +1653,6 @@ dependencies = [ "semver 0.9.0", ] -[[package]] -name = "rustix" -version = "0.35.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af895b90e5c071badc3136fc10ff0bcfc98747eadbaf43ed8f214e07ba8f8477" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "rustversion" version = "1.0.9" @@ -1585,12 +1674,45 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static", + "windows-sys", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "security-framework" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "0.9.0" @@ -1646,6 +1768,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.3", + "ryu", + "serde", +] + [[package]] name = "sha1" version = "0.6.1" @@ -1717,6 +1851,15 @@ dependencies = [ "walkdir", ] +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.9.0" @@ -1877,16 +2020,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "terminal_size" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8440c860cf79def6164e4a0a983bcc2305d82419177a0e0c71930d049e3ac5a1" -dependencies = [ - "rustix", - "windows-sys", -] - [[package]] name = "textwrap" version = "0.15.1" @@ -2027,6 +2160,30 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -2176,6 +2333,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.83" @@ -2205,6 +2374,16 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +[[package]] +name = "web-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2279,6 +2458,15 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "winstructs" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 59c83f7d..bf36ee69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ crossbeam-utils = "0.8.*" num-format = "*" comfy-table = "6.*" pulldown-cmark = { version = "0.9.*", default-features = false, features = ["simd"] } +reqwest = {version = "0.11.*", features = ["blocking", "json"]} [build-dependencies] static_vcruntime = "2.*" diff --git a/README-Japanese.md b/README-Japanese.md index 46aeb403..2f34460f 100644 --- a/README-Japanese.md +++ b/README-Japanese.md @@ -370,7 +370,7 @@ macOSの環境設定から「セキュリティとプライバシー」を開き * `--level-tuning`: アラート`level`のカスタムチューニング * `-L, --logon-summary`: ログオンイベントのサマリを出力する。 * `-P, --pivot-keywords-list`: ピボットする不審なキーワードのリスト作成。 -* `-s, --statistics`: イベントIDに基づくイベントの合計と割合の集計を出力する。 +* `-M, --metrics`: イベントIDに基づくイベントの合計と割合の集計を出力する。 * `--set-default-profile`: デフォルトプロファイルを変更する。 * `-u, --update`: GitHubの[hayabusa-rules](https://github.com/Yamato-Security/hayabusa-rules)リポジトリにある最新のルールに同期させる。 @@ -419,8 +419,8 @@ OTHER-ACTIONS: --contributors コントリビュータの一覧表示 -L, --logon-summary 成功と失敗したログオン情報の要約を出力する --level-tuning [] ルールlevelのチューニング (デフォルト: ./rules/config/level_tuning.txt) + -M, --metrics イベントIDの統計情報を表示する -p, --pivot-keywords-list ピボットキーワードの一覧作成 - -s, --statistics イベントIDの統計情報を表示する --set-default-profile デフォルトの出力コンフィグを設定する -u, --update-rules rulesフォルダをhayabusa-rulesのgithubリポジトリの最新版に更新する @@ -510,12 +510,13 @@ hayabusa-1.6.0-win-x64.exe -l -m critical -p -o keywords * イベントIDの統計情報を出力する: ```bash -hayabusa-1.6.0-win-x64.exe -f Security.evtx -s +hayabusa-1.6.0-win-x64.exe -f Security.evtx -M ``` + * ログオンサマリを出力する: ```bash -hayabusa-1.6.0-win-x64.exe -L -f Security.evtx -s +hayabusa-1.6.0-win-x64.exe -L -f Security.evtx -M ``` * 詳細なメッセージを出力する(処理に時間がかかるファイル、パースエラー等を特定するのに便利): diff --git a/README.md b/README.md index a5c6a3a7..ab7e96be 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ You can learn how to import CSV files into Timesketch [here](doc/TimesketchImpor * Threat hunting based on IoC signatures written in easy to read/create/edit YML based hayabusa rules. * Sigma rule support to convert sigma rules to hayabusa rules. * Currently it supports the most sigma rules compared to other similar tools and even supports count rules and new aggregators such as `|equalsfield`. -* Event log statistics. (Useful for getting a picture of what types of events there are and for tuning your log settings.) +* Event ID metrics. (Useful for getting a picture of what types of events there are and for tuning your log settings.) * Rule tuning configuration by excluding unneeded or noisy rules. * MITRE ATT&CK mapping of tactics. * Rule level tuning. @@ -361,7 +361,7 @@ You should now be able to run hayabusa. * `--level-tuning`: Custom tune the alerts' `level`. * `-L, --logon-summary`: Print a summary of logon events. * `-P, --pivot-keywords-list`: Print a list of suspicious keywords to pivot on. -* `-s, --statistics`: Print metrics of the count and percentage of events based on Event ID. +* `-M, --metrics`: Print metrics of the number and percentage of events based on Event ID. * `--set-default-profile`: Change the default profile. * `-u, --update`: Sync the rules to the latest rules in the [hayabusa-rules](https://github.com/Yamato-Security/hayabusa-rules) GitHub repository. @@ -410,8 +410,8 @@ OTHER-ACTIONS: --contributors Print the list of contributors -L, --logon-summary Print a summary of successful and failed logons --level-tuning [] Tune alert levels (default: ./rules/config/level_tuning.txt) + -M, --metrics Print event ID metrics -p, --pivot-keywords-list Create a list of pivot keywords - -s, --statistics Print statistics of event IDs --set-default-profile Set default output profile -u, --update-rules Update to the latest rules in the hayabusa-rules github repository @@ -498,16 +498,16 @@ hayabusa-1.6.0-win-x64.exe -l -m low hayabusa-1.6.0-win-x64.exe -l -m critical -p -o keywords ``` -* Print Event ID statistics: +* Print Event ID metrics: ```bash -hayabusa-1.6.0-win-x64.exe -f Security.evtx -s +hayabusa-1.6.0-win-x64.exe -f Security.evtx -M ``` * Print logon summary: ```bash -hayabusa-1.6.0-win-x64.exe -L -f Security.evtx -s +hayabusa-1.6.0-win-x64.exe -L -f Security.evtx -M ``` * Print verbose information (useful for determining which files take long to process, parsing errors, etc...): diff --git a/contributors.txt b/contributors.txt index dd3e8a57..e61924a1 100644 --- a/contributors.txt +++ b/contributors.txt @@ -2,7 +2,7 @@ Hayabusa was possible thanks to the following people (in alphabetical order): Akira Nishikawa (@nishikawaakira): Previous lead developer, core hayabusa rule support, etc... Fukusuke Takahashi (fukuseket): Static compiling for Windows, race condition and other bug fixes. -Garigariganzy (@garigariganzy31): Developer, event ID statistics implementation, etc... +Garigariganzy (@garigariganzy31): Developer, event ID metrics implementation, etc... ItiB (@itiB_S144) : Core developer, sigmac hayabusa backend, rule creation, etc... James Takai / hachiyone(@hach1yon): Current lead developer, tokio multi-threading, sigma aggregation logic, sigmac backend, rule creation, sigma count implementation etc… Kazuminn (@k47_um1n): Core Developer diff --git a/doc/ElasticStackImport/ElasticStackImport-English.md b/doc/ElasticStackImport/ElasticStackImport-English.md index 4a8c96a3..7a3219e9 100644 --- a/doc/ElasticStackImport/ElasticStackImport-English.md +++ b/doc/ElasticStackImport/ElasticStackImport-English.md @@ -51,7 +51,7 @@ As shown below, click on `Advanced` and perform the following settings before cl 1. Title the `Index name` as `evtxlogs-hayabusa`. 2. Under `Index settings`, add `, "number_of_replicas": 0` so that the index health status does not turn yellow. -3. Under `Mappings`, change the `RuleTitle` type of `text` to `keyword` so that we can do statistics on the rule titles and change the `EventID` type of `long` to `keyword` in order to import without errors. +3. Under `Mappings`, change the `RuleTitle` type of `text` to `keyword` so that we can calculate metrics on the rule titles and change the `EventID` type of `long` to `keyword` in order to import without errors. 4. Under `Ingest pipeline`, add `, "field": "Timestamp"` under the `remove` section. Timestamps will be displayed as `@timestamp` so this duplicate field is not needed. Also, delete the following in order to import without errors: ``` { diff --git a/rules b/rules index fe99c87c..2b0f88d1 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit fe99c87c886ca5b66b5e67242eeddfacc469d420 +Subproject commit 2b0f88d1c09b5b9979b99686a29a244993508210 diff --git a/src/detections/configs.rs b/src/detections/configs.rs index 8e8a2e49..662d1b04 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -188,9 +188,9 @@ pub struct Config { #[clap(help_heading = Some("ADVANCED"), short, long = "thread-number", value_name = "NUMBER")] pub thread_number: Option, - /// Print statistics of event IDs - #[clap(help_heading = Some("OTHER-ACTIONS"), short, long)] - pub statistics: bool, + /// Print event ID metrics + #[clap(help_heading = Some("OTHER-ACTIONS"), short='M', long)] + pub metrics: bool, /// Print a summary of successful and failed logons #[clap(help_heading = Some("OTHER-ACTIONS"), short = 'L', long = "logon-summary")] @@ -270,11 +270,11 @@ impl ConfigReader<'_> { args: parse.clone(), headless_help: String::default(), event_timeline_config: load_eventcode_info( - utils::check_setting_path(&parse.config, "statistics_event_info.txt", false) + utils::check_setting_path(&parse.config, "event_id_info.txt", false) .unwrap_or_else(|| { utils::check_setting_path( &CURRENT_EXE_PATH.to_path_buf(), - "rules/config/statistics_event_info.txt", + "rules/config/event_id_info.txt", true, ) .unwrap() @@ -585,7 +585,7 @@ fn load_eventcode_info(path: &str) -> EventInfoConfig { return config; } - // statistics_event_infoが読み込めなかったらエラーで終了とする。 + // event_id_info.txtが読み込めなかったらエラーで終了とする。 read_result.unwrap().into_iter().for_each(|line| { if line.len() != 2 { return; diff --git a/src/detections/detection.rs b/src/detections/detection.rs index b33fc109..9fb7557b 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -14,7 +14,7 @@ use crate::detections::message::DetectInfo; use crate::detections::message::ERROR_LOG_STACK; use crate::detections::message::{CH_CONFIG, DEFAULT_DETAILS, TAGS_CONFIG}; use crate::detections::message::{ - LOGONSUMMARY_FLAG, PIVOT_KEYWORD_LIST_FLAG, QUIET_ERRORS_FLAG, STATISTICS_FLAG, + LOGONSUMMARY_FLAG, METRICS_FLAG, PIVOT_KEYWORD_LIST_FLAG, QUIET_ERRORS_FLAG, }; use crate::detections::pivot::insert_pivot_keyword; use crate::detections::rule; @@ -600,7 +600,7 @@ impl Detection { st_rc: &HashMap, err_rc: &u128, ) { - if *STATISTICS_FLAG { + if *METRICS_FLAG { return; } let mut sorted_ld_rc: Vec<(&String, &u128)> = ld_rc.iter().collect(); diff --git a/src/detections/message.rs b/src/detections/message.rs index 74a48783..9f46e0bf 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -46,7 +46,7 @@ lazy_static! { ); pub static ref QUIET_ERRORS_FLAG: bool = configs::CONFIG.read().unwrap().args.quiet_errors; pub static ref ERROR_LOG_STACK: Mutex> = Mutex::new(Vec::new()); - pub static ref STATISTICS_FLAG: bool = configs::CONFIG.read().unwrap().args.statistics; + pub static ref METRICS_FLAG: bool = configs::CONFIG.read().unwrap().args.metrics; pub static ref LOGONSUMMARY_FLAG: bool = configs::CONFIG.read().unwrap().args.logon_summary; pub static ref TAGS_CONFIG: HashMap = create_output_filter_config( utils::check_setting_path(&CURRENT_EXE_PATH.to_path_buf(), "config/mitre_tactics.txt", true) diff --git a/src/detections/utils.rs b/src/detections/utils.rs index 837da55d..259dc32b 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -410,7 +410,7 @@ pub fn check_rule_config() -> Result<(), String> { "target_event_IDs.txt", "default_details.txt", "level_tuning.txt", - "statistics_event_info.txt", + "event_id_info.txt", "eventkey_alias.txt", ]; let mut not_exist_file = vec![]; diff --git a/src/main.rs b/src/main.rs index 489bdad4..1adb19f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,8 +11,8 @@ use hayabusa::detections::configs::{load_pivot_keywords, TargetEventTime, TARGET use hayabusa::detections::configs::{CONFIG, CURRENT_EXE_PATH}; use hayabusa::detections::detection::{self, EvtxRecordInfo}; use hayabusa::detections::message::{ - AlertMessage, ERROR_LOG_PATH, ERROR_LOG_STACK, LOGONSUMMARY_FLAG, PIVOT_KEYWORD_LIST_FLAG, - QUIET_ERRORS_FLAG, STATISTICS_FLAG, + AlertMessage, ERROR_LOG_PATH, ERROR_LOG_STACK, LOGONSUMMARY_FLAG, METRICS_FLAG, + PIVOT_KEYWORD_LIST_FLAG, QUIET_ERRORS_FLAG, }; use hayabusa::detections::pivot::PivotKeyword; use hayabusa::detections::pivot::PIVOT_KEYWORD; @@ -20,7 +20,7 @@ use hayabusa::detections::rule::{get_detection_keys, RuleNode}; use hayabusa::omikuji::Omikuji; use hayabusa::options::htmlreport::{self, HTML_REPORTER}; use hayabusa::options::profile::PROFILES; -use hayabusa::options::{level_tuning::LevelTuning, update_rules::UpdateRules}; +use hayabusa::options::{level_tuning::LevelTuning, update::Update}; use hayabusa::{afterfact::after_fact, detections::utils}; use hayabusa::{detections::configs, timeline::timelines::Timeline}; use hayabusa::{detections::utils::write_color_buffer, filter}; @@ -128,9 +128,19 @@ impl App { } if configs::CONFIG.read().unwrap().args.update_rules { - match UpdateRules::update_rules( - configs::CONFIG.read().unwrap().args.rules.to_str().unwrap(), - ) { + // エラーが出た場合はインターネット接続がそもそもできないなどの問題点もあるためエラー等の出力は行わない + let latest_version_data = if let Ok(data) = Update::get_latest_hayabusa_version() { + data + } else { + None + }; + let now_version = &format!( + "v{}", + configs::CONFIG.read().unwrap().app.get_version().unwrap() + ); + + match Update::update_rules(configs::CONFIG.read().unwrap().args.rules.to_str().unwrap()) + { Ok(output) => { if output != "You currently have the latest rules." { write_color_buffer( @@ -147,6 +157,33 @@ impl App { } } println!(); + if latest_version_data.is_some() + && now_version + != &latest_version_data + .as_ref() + .unwrap_or(now_version) + .replace('\"', "") + { + write_color_buffer( + &BufferWriter::stdout(ColorChoice::Always), + None, + &format!( + "There is a new version of Hayabusa: {}", + latest_version_data.unwrap().replace('\"', "") + ), + true, + ) + .ok(); + write_color_buffer( + &BufferWriter::stdout(ColorChoice::Always), + None, + "You can download it at https://github.com/Yamato-Security/hayabusa/releases", + true, + ) + .ok(); + } + println!(); + return; } // 実行時のexeファイルのパスをベースに変更する必要があるためデフォルトの値であった場合はそのexeファイルと同一階層を探すようにする @@ -203,11 +240,11 @@ impl App { return; } - if *STATISTICS_FLAG { + if *METRICS_FLAG { write_color_buffer( &BufferWriter::stdout(ColorChoice::Always), None, - "Generating Event ID Statistics", + "Generating Event ID Metrics", true, ) .ok(); @@ -613,7 +650,7 @@ impl App { } println!(); detection.add_aggcondition_msges(&self.rt); - if !(*STATISTICS_FLAG || *LOGONSUMMARY_FLAG || *PIVOT_KEYWORD_LIST_FLAG) { + if !(*METRICS_FLAG || *LOGONSUMMARY_FLAG || *PIVOT_KEYWORD_LIST_FLAG) { after_fact(total_records); } } @@ -695,7 +732,7 @@ impl App { // timeline機能の実行 tl.start(&records_per_detect); - if !(*STATISTICS_FLAG || *LOGONSUMMARY_FLAG) { + if !(*METRICS_FLAG || *LOGONSUMMARY_FLAG) { // ruleファイルの検知 detection = detection.start(&self.rt, records_per_detect); } diff --git a/src/options/mod.rs b/src/options/mod.rs index 848ff1c0..26cca6fb 100644 --- a/src/options/mod.rs +++ b/src/options/mod.rs @@ -1,4 +1,4 @@ pub mod htmlreport; pub mod level_tuning; pub mod profile; -pub mod update_rules; +pub mod update; diff --git a/src/options/update_rules.rs b/src/options/update.rs similarity index 86% rename from src/options/update_rules.rs rename to src/options/update.rs index 6d501777..0fa81367 100644 --- a/src/options/update_rules.rs +++ b/src/options/update.rs @@ -4,6 +4,7 @@ use crate::filter; use crate::yaml::ParseYaml; use chrono::{DateTime, Local, TimeZone}; use git2::Repository; +use serde_json::Value; use std::fs::{self}; use std::path::Path; @@ -16,9 +17,26 @@ use std::fs::create_dir; use termcolor::{BufferWriter, ColorChoice}; -pub struct UpdateRules {} +pub struct Update {} + +impl Update { + /// get latest hayabusa version number. + pub fn get_latest_hayabusa_version() -> Result, Box> { + let res = reqwest::blocking::Client::new() + .get("https://api.github.com/repos/Yamato-Security/hayabusa/releases/latest") + .header("User-Agent", "HayabusaUpdateChecker") + .header("Accept", "application/vnd.github.v3+json") + .send()?; + let text = res.text()?; + let json_res: Value = serde_json::from_str(&text)?; + + if json_res["tag_name"].is_null() { + Ok(None) + } else { + Ok(Some(json_res["tag_name"].to_string())) + } + } -impl UpdateRules { /// update rules(hayabusa-rules subrepository) pub fn update_rules(rule_path: &str) -> Result { let mut result; @@ -35,14 +53,14 @@ impl UpdateRules { ) .ok(); // execution git clone of hayabusa-rules repository when failed open hayabusa repository. - result = UpdateRules::clone_rules(Path::new(rule_path)); + result = Update::clone_rules(Path::new(rule_path)); } else if hayabusa_rule_repo.is_ok() { // case of exist hayabusa-rules repository - UpdateRules::_repo_main_reset_hard(hayabusa_rule_repo.as_ref().unwrap())?; + Update::_repo_main_reset_hard(hayabusa_rule_repo.as_ref().unwrap())?; // case of failed fetching origin/main, git clone is not executed so network error has occurred possibly. - prev_modified_rules = UpdateRules::get_updated_rules(rule_path, &prev_modified_time); + prev_modified_rules = Update::get_updated_rules(rule_path, &prev_modified_time); prev_modified_time = fs::metadata(rule_path).unwrap().modified().unwrap(); - result = UpdateRules::pull_repository(&hayabusa_rule_repo.unwrap()); + result = Update::pull_repository(&hayabusa_rule_repo.unwrap()); } else { // case of no exist hayabusa-rules repository in rules. // execute update because submodule information exists if hayabusa repository exists submodule information. @@ -61,7 +79,7 @@ impl UpdateRules { for mut submodule in submodules { submodule.update(true, None)?; let submodule_repo = submodule.open()?; - if let Err(e) = UpdateRules::pull_repository(&submodule_repo) { + if let Err(e) = Update::pull_repository(&submodule_repo) { AlertMessage::alert(&format!("Failed submodule update. {}", e)).ok(); is_success_submodule_update = false; } @@ -80,16 +98,13 @@ impl UpdateRules { ) .ok(); // execution git clone of hayabusa-rules repository when failed open hayabusa repository. - result = UpdateRules::clone_rules(rules_path); + result = Update::clone_rules(rules_path); } } if result.is_ok() { - let updated_modified_rules = - UpdateRules::get_updated_rules(rule_path, &prev_modified_time); - result = UpdateRules::print_diff_modified_rule_dates( - prev_modified_rules, - updated_modified_rules, - ); + let updated_modified_rules = Update::get_updated_rules(rule_path, &prev_modified_time); + result = + Update::print_diff_modified_rule_dates(prev_modified_rules, updated_modified_rules); } result } @@ -254,7 +269,7 @@ impl UpdateRules { #[cfg(test)] mod tests { - use crate::options::update_rules::UpdateRules; + use crate::options::update::Update; use std::time::SystemTime; #[test] @@ -262,12 +277,12 @@ mod tests { let prev_modified_time: SystemTime = SystemTime::UNIX_EPOCH; let prev_modified_rules = - UpdateRules::get_updated_rules("test_files/rules/level_yaml", &prev_modified_time); + Update::get_updated_rules("test_files/rules/level_yaml", &prev_modified_time); assert_eq!(prev_modified_rules.len(), 5); let target_time: SystemTime = SystemTime::now(); let prev_modified_rules2 = - UpdateRules::get_updated_rules("test_files/rules/level_yaml", &target_time); + Update::get_updated_rules("test_files/rules/level_yaml", &target_time); assert_eq!(prev_modified_rules2.len(), 0); } } diff --git a/src/timeline/statistics.rs b/src/timeline/metrics.rs similarity index 93% rename from src/timeline/statistics.rs rename to src/timeline/metrics.rs index 6e6982e1..d04e2ddd 100644 --- a/src/timeline/statistics.rs +++ b/src/timeline/metrics.rs @@ -1,9 +1,9 @@ -use crate::detections::message::{LOGONSUMMARY_FLAG, STATISTICS_FLAG}; +use crate::detections::message::{LOGONSUMMARY_FLAG, METRICS_FLAG}; use crate::detections::{detection::EvtxRecordInfo, utils}; use hashbrown::HashMap; #[derive(Debug)] -pub struct EventStatistics { +pub struct EventMetrics { pub total: usize, pub filepath: String, pub start_time: String, @@ -14,7 +14,7 @@ pub struct EventStatistics { /** * Windows Event Logの統計情報を出力する */ -impl EventStatistics { +impl EventMetrics { pub fn new( total: usize, filepath: String, @@ -22,8 +22,8 @@ impl EventStatistics { end_time: String, stats_list: HashMap, stats_login_list: HashMap, - ) -> EventStatistics { - EventStatistics { + ) -> EventMetrics { + EventMetrics { total, filepath, start_time, @@ -34,8 +34,8 @@ impl EventStatistics { } pub fn evt_stats_start(&mut self, records: &[EvtxRecordInfo]) { - // 引数でstatisticsオプションが指定されている時だけ、統計情報を出力する。 - if !*STATISTICS_FLAG { + // 引数でmetricsオプションが指定されている時だけ、統計情報を出力する。 + if !*METRICS_FLAG { return; } diff --git a/src/timeline/mod.rs b/src/timeline/mod.rs index c6200b52..7557f9f8 100644 --- a/src/timeline/mod.rs +++ b/src/timeline/mod.rs @@ -1,2 +1,2 @@ -pub mod statistics; +pub mod metrics; pub mod timelines; diff --git a/src/timeline/timelines.rs b/src/timeline/timelines.rs index a0cad83a..751643cd 100644 --- a/src/timeline/timelines.rs +++ b/src/timeline/timelines.rs @@ -1,13 +1,13 @@ -use crate::detections::message::{LOGONSUMMARY_FLAG, STATISTICS_FLAG}; +use crate::detections::message::{LOGONSUMMARY_FLAG, METRICS_FLAG}; use crate::detections::{configs::CONFIG, detection::EvtxRecordInfo}; use prettytable::{Cell, Row, Table}; -use super::statistics::EventStatistics; +use super::metrics::EventMetrics; use hashbrown::HashMap; #[derive(Debug)] pub struct Timeline { - pub stats: EventStatistics, + pub stats: EventMetrics, } impl Default for Timeline { @@ -26,7 +26,7 @@ impl Timeline { let statsloginlst = HashMap::new(); let statistic = - EventStatistics::new(totalcnt, filepath, starttm, endtm, statslst, statsloginlst); + EventMetrics::new(totalcnt, filepath, starttm, endtm, statslst, statsloginlst); Timeline { stats: statistic } } @@ -36,7 +36,7 @@ impl Timeline { } pub fn tm_stats_dsp_msg(&mut self) { - if !*STATISTICS_FLAG { + if !*METRICS_FLAG { return; } // 出力メッセージ作成 @@ -98,7 +98,7 @@ impl Timeline { .event_timeline_config .get_event_id(*event_id) .is_some(); - // statistics_event_info.txtに登録あるものは情報設定 + // event_id_info.txtに登録あるものは情報設定 if conf { // 出力メッセージ1行作成 msges.push(format!(