Merge branch 'main' into 583-enhancement-output-processing-rules-msg-and-rule-status-metrics
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
- LinuxとmacOSのバイナリサイズをより小さくするために、デバッグシンボルをストリップします。(#568) (@YamatoSecurity)
|
- LinuxとmacOSのバイナリサイズをより小さくするために、デバッグシンボルをストリップします。(#568) (@YamatoSecurity)
|
||||||
- 新たな時刻表示のオプションとして`--US-time`、`--US-military-time`、`--European-time`の3つを追加した (#574) (@hitenkoku)
|
- 新たな時刻表示のオプションとして`--US-time`、`--US-military-time`、`--European-time`の3つを追加した (#574) (@hitenkoku)
|
||||||
- `--rfc-3339` オプションの時刻表示形式を変更した。 (#574) (@hitenkoku)
|
- `--rfc-3339` オプションの時刻表示形式を変更した。 (#574) (@hitenkoku)
|
||||||
|
- `-R/ --display-record-id`オプションを`-R/ --hide-record-id`に変更。レコードIDはデフォルトで出力するようにして`-R`オプションを付けた際に表示しないように変更した。(#579) (@hitenkoku)
|
||||||
- ルール読み込み時のメッセージを追加した。 (#583) (@hitenkoku)
|
- ルール読み込み時のメッセージを追加した。 (#583) (@hitenkoku)
|
||||||
|
|
||||||
**バグ修正:**
|
**バグ修正:**
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
- Strip debug symbols by default for smaller Linux and macOS binaries. (#568) (@YamatoSecurity)
|
- Strip debug symbols by default for smaller Linux and macOS binaries. (#568) (@YamatoSecurity)
|
||||||
- Added new output time format options. (`--US-time`, `--US-military-time`, `--European-time`) (#574) (@hitenkoku)
|
- Added new output time format options. (`--US-time`, `--US-military-time`, `--European-time`) (#574) (@hitenkoku)
|
||||||
- Changed output time format when `--rfc-3339` option is enabled. (#574) (@hitenkoku)
|
- Changed output time format when `--rfc-3339` option is enabled. (#574) (@hitenkoku)
|
||||||
|
- Changed the `-R / --display-record-id` option to `-R / --hide-record-id` and now by default the event record ID is displayed. You can hide the record ID with `-R / --hide-record-id`. (#579) (@hitenkoku)
|
||||||
- Added rule loading message. (#583) (@hitenkoku)
|
- Added rule loading message. (#583) (@hitenkoku)
|
||||||
|
|
||||||
**Bug Fixes:**
|
**Bug Fixes:**
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ Hayabusaは、日本の[Yamato Security](https://yamatosecurity.connpass.com/)
|
|||||||
- [ログオン情報の要約](#ログオン情報の要約)
|
- [ログオン情報の要約](#ログオン情報の要約)
|
||||||
- [サンプルevtxファイルでHayabusaをテストする](#サンプルevtxファイルでhayabusaをテストする)
|
- [サンプルevtxファイルでHayabusaをテストする](#サンプルevtxファイルでhayabusaをテストする)
|
||||||
- [Hayabusaの出力](#hayabusaの出力)
|
- [Hayabusaの出力](#hayabusaの出力)
|
||||||
|
- [Levelの省略](#levelの省略)
|
||||||
- [MITRE ATT&CK戦術の省略](#mitre-attck戦術の省略)
|
- [MITRE ATT&CK戦術の省略](#mitre-attck戦術の省略)
|
||||||
- [Channel情報の省略](#channel情報の省略)
|
- [Channel情報の省略](#channel情報の省略)
|
||||||
- [プログレスバー](#プログレスバー)
|
- [プログレスバー](#プログレスバー)
|
||||||
@@ -329,7 +330,7 @@ USAGE:
|
|||||||
-C, --config [RULE_CONFIG_DIRECTORY] 'ルールフォルダのコンフィグディレクトリ(デフォルト: .\rules\config)'
|
-C, --config [RULE_CONFIG_DIRECTORY] 'ルールフォルダのコンフィグディレクトリ(デフォルト: .\rules\config)'
|
||||||
-o, --output [CSV_TIMELINE] 'タイムラインをCSV形式で保存する。(例: results.csv)'
|
-o, --output [CSV_TIMELINE] 'タイムラインをCSV形式で保存する。(例: results.csv)'
|
||||||
--all-tags '出力したCSVファイルにルール内のタグ情報を全て出力する。'
|
--all-tags '出力したCSVファイルにルール内のタグ情報を全て出力する。'
|
||||||
-R, --display-record-id 'イベントレコードIDを出力する。'
|
-R, --hide-record-id 'イベントレコードIDを表示しない。'
|
||||||
-v, --verbose '詳細な情報を出力する。'
|
-v, --verbose '詳細な情報を出力する。'
|
||||||
-V, --visualize-timeline 'イベント頻度タイムラインを出力する。'
|
-V, --visualize-timeline 'イベント頻度タイムラインを出力する。'
|
||||||
-D, --enable-deprecated-rules 'Deprecatedルールを有効にする。'
|
-D, --enable-deprecated-rules 'Deprecatedルールを有効にする。'
|
||||||
@@ -499,6 +500,7 @@ Hayabusaの結果を標準出力に表示しているとき(デフォルト)
|
|||||||
* `Event ID`: イベントログの`<Event><System><EventID>`フィールドから来ています。
|
* `Event ID`: イベントログの`<Event><System><EventID>`フィールドから来ています。
|
||||||
* `Level`: YML検知ルールの`level`フィールドから来ています。(例:`informational`, `low`, `medium`, `high`, `critical`) デフォルトでは、すべてのレベルのアラートとイベントが出力されますが、`-m`オプションで最低のレベルを指定することができます。例えば`-m high`オプションを付けると、`high`と`critical`アラートしか出力されません。
|
* `Level`: YML検知ルールの`level`フィールドから来ています。(例:`informational`, `low`, `medium`, `high`, `critical`) デフォルトでは、すべてのレベルのアラートとイベントが出力されますが、`-m`オプションで最低のレベルを指定することができます。例えば`-m high`オプションを付けると、`high`と`critical`アラートしか出力されません。
|
||||||
* `Title`: YML検知ルールの`title`フィールドから来ています。
|
* `Title`: YML検知ルールの`title`フィールドから来ています。
|
||||||
|
* `RecordID`: イベントレコードIDです。`<Event><System><EventRecordID>`フィールドから来ています。`-R`もしくは`--hide-record-id`オプションを付けると表示されません。
|
||||||
* `Details`: YML検知ルールの`details`フィールドから来ていますが、このフィールドはHayabusaルールにしかありません。このフィールドはアラートとイベントに関する追加情報を提供し、ログの`<Event><System><EventData>`部分から有用なデータを抽出することができます。イベントキーのマッピングが間違っている場合、もしくはフィールドが存在しない場合で抽出ができなかった箇所は`n/a` (not available)と記載されます。
|
* `Details`: YML検知ルールの`details`フィールドから来ていますが、このフィールドはHayabusaルールにしかありません。このフィールドはアラートとイベントに関する追加情報を提供し、ログの`<Event><System><EventData>`部分から有用なデータを抽出することができます。イベントキーのマッピングが間違っている場合、もしくはフィールドが存在しない場合で抽出ができなかった箇所は`n/a` (not available)と記載されます。
|
||||||
|
|
||||||
CSVファイルとして保存する場合、以下の列が追加されます:
|
CSVファイルとして保存する場合、以下の列が追加されます:
|
||||||
@@ -507,9 +509,18 @@ CSVファイルとして保存する場合、以下の列が追加されます:
|
|||||||
* `Rule Path`: アラートまたはイベントを生成した検知ルールへのパス。
|
* `Rule Path`: アラートまたはイベントを生成した検知ルールへのパス。
|
||||||
* `File Path`: アラートまたはイベントを起こしたevtxファイルへのパス。
|
* `File Path`: アラートまたはイベントを起こしたevtxファイルへのパス。
|
||||||
|
|
||||||
`-R`もしくは`--display-record-id`オプションを指定した場合、`<Event><System><EventRecordID>`の情報が`RecordID`カラムに出力されます。
|
|
||||||
`-F`もしくは`--full-data`オプションを指定した場合、全てのフィールド情報が`RecordInformation`カラムにで出力されます。
|
`-F`もしくは`--full-data`オプションを指定した場合、全てのフィールド情報が`RecordInformation`カラムにで出力されます。
|
||||||
|
|
||||||
|
## Levelの省略
|
||||||
|
|
||||||
|
簡潔に出力するためにLevelを以下のように省略し出力しています。
|
||||||
|
|
||||||
|
* `crit`: `critical`
|
||||||
|
* `high`: `high`
|
||||||
|
* `med `: `med`
|
||||||
|
* `low `: `low`
|
||||||
|
* `info`: `informational`
|
||||||
|
|
||||||
## MITRE ATT&CK戦術の省略
|
## MITRE ATT&CK戦術の省略
|
||||||
|
|
||||||
簡潔に出力するためにMITRE ATT&CKの戦術を以下のように省略しています。
|
簡潔に出力するためにMITRE ATT&CKの戦術を以下のように省略しています。
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -60,6 +60,7 @@ Hayabusa is a **Windows event log fast forensics timeline generator** and **thre
|
|||||||
- [Logon Summary Generator](#logon-summary-generator)
|
- [Logon Summary Generator](#logon-summary-generator)
|
||||||
- [Testing Hayabusa on Sample Evtx Files](#testing-hayabusa-on-sample-evtx-files)
|
- [Testing Hayabusa on Sample Evtx Files](#testing-hayabusa-on-sample-evtx-files)
|
||||||
- [Hayabusa Output](#hayabusa-output)
|
- [Hayabusa Output](#hayabusa-output)
|
||||||
|
- [Level Abbrevations](#level-abbrevations)
|
||||||
- [MITRE ATT&CK Tactics Abbreviations](#mitre-attck-tactics-abbreviations)
|
- [MITRE ATT&CK Tactics Abbreviations](#mitre-attck-tactics-abbreviations)
|
||||||
- [Channel Abbreviations](#channel-abbreviations)
|
- [Channel Abbreviations](#channel-abbreviations)
|
||||||
- [Progress Bar](#progress-bar)
|
- [Progress Bar](#progress-bar)
|
||||||
@@ -327,7 +328,7 @@ USAGE:
|
|||||||
-C, --config [RULE_CONFIG_DIRECTORY] 'Rule config folder. (Default: .\rules\config)'
|
-C, --config [RULE_CONFIG_DIRECTORY] 'Rule config folder. (Default: .\rules\config)'
|
||||||
-o, --output [CSV_TIMELINE] 'Save the timeline in CSV format. (Ex: results.csv)'
|
-o, --output [CSV_TIMELINE] 'Save the timeline in CSV format. (Ex: results.csv)'
|
||||||
--all-tags 'Output all tags when saving to a CSV file.'
|
--all-tags 'Output all tags when saving to a CSV file.'
|
||||||
-R, --display-record-id 'Display event record ID.'
|
-R, --hide-record-id 'Do not display the EventRecordID number.'
|
||||||
-v, --verbose 'Output verbose information.'
|
-v, --verbose 'Output verbose information.'
|
||||||
-V, --visualize-timeline 'Output event frequency timeline.'
|
-V, --visualize-timeline 'Output event frequency timeline.'
|
||||||
-D, --enable-deprecated-rules 'Enable rules marked as deprecated.'
|
-D, --enable-deprecated-rules 'Enable rules marked as deprecated.'
|
||||||
@@ -497,6 +498,7 @@ When hayabusa output is being displayed to the screen (the default), it will dis
|
|||||||
* `Channel`: The name of log. This comes from the `<Event><System><Channel>` field in the event log.
|
* `Channel`: The name of log. This comes from the `<Event><System><Channel>` field in the event log.
|
||||||
* `Event ID`: This comes from the `<Event><System><EventID>` field in the event log.
|
* `Event ID`: This comes from the `<Event><System><EventID>` field in the event log.
|
||||||
* `Level`: This comes from the `level` field in the YML detection rule. (`informational`, `low`, `medium`, `high`, `critical`) By default, all level alerts will be displayed but you can set the minimum level with `-m`. For example, you can set `-m high`) in order to only scan for and display high and critical alerts.
|
* `Level`: This comes from the `level` field in the YML detection rule. (`informational`, `low`, `medium`, `high`, `critical`) By default, all level alerts will be displayed but you can set the minimum level with `-m`. For example, you can set `-m high`) in order to only scan for and display high and critical alerts.
|
||||||
|
* `RecordID`: This comes from the `<Event><System><EventRecordID>` field in the event log. You can hidde this output with the `-R` or `--hide-record-id` option.
|
||||||
* `Title`: This comes from the `title` field in the YML detection rule.
|
* `Title`: This comes from the `title` field in the YML detection rule.
|
||||||
* `Details`: This comes from the `details` field in the YML detection rule, however, only hayabusa rules have this field. This field gives extra information about the alert or event and can extract useful data from the `<Event><System><EventData>` portion of the log. For example, usernames, command line information, process information, etc... When a placeholder points to a field that does not exist or there is an incorrect alias mapping, it will be outputted as `n/a` (not available).
|
* `Details`: This comes from the `details` field in the YML detection rule, however, only hayabusa rules have this field. This field gives extra information about the alert or event and can extract useful data from the `<Event><System><EventData>` portion of the log. For example, usernames, command line information, process information, etc... When a placeholder points to a field that does not exist or there is an incorrect alias mapping, it will be outputted as `n/a` (not available).
|
||||||
|
|
||||||
@@ -506,9 +508,18 @@ The following additional columns will be added to the output when saving to a CS
|
|||||||
* `Rule Path`: The path to the detection rule that generated the alert or event.
|
* `Rule Path`: The path to the detection rule that generated the alert or event.
|
||||||
* `File Path`: The path to the evtx file that caused the alert or event.
|
* `File Path`: The path to the evtx file that caused the alert or event.
|
||||||
|
|
||||||
If you add the `-R` or `--display-record-id` option, a `RecordId` column with event record ID values taken from `<Event><System><EventRecordID>` will also be added.
|
|
||||||
If you add the `-F` or `--full-data` option, a `RecordInformation` column with all field information will also be added.
|
If you add the `-F` or `--full-data` option, a `RecordInformation` column with all field information will also be added.
|
||||||
|
|
||||||
|
## Level Abbrevations
|
||||||
|
|
||||||
|
In order to save space, we use the following abbrevations when displaying the alert `level`.
|
||||||
|
|
||||||
|
* `crit`: `critical`
|
||||||
|
* `high`: `high`
|
||||||
|
* `med `: `med`
|
||||||
|
* `low `: `low`
|
||||||
|
* `info`: `informational`
|
||||||
|
|
||||||
## MITRE ATT&CK Tactics Abbreviations
|
## MITRE ATT&CK Tactics Abbreviations
|
||||||
|
|
||||||
In order to save space, we use the following abbreviations when displaying MITRE ATT&CK tactic tags.
|
In order to save space, we use the following abbreviations when displaying MITRE ATT&CK tactic tags.
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 356 KiB After Width: | Height: | Size: 309 KiB |
@@ -1,6 +1,6 @@
|
|||||||
use crate::detections::configs;
|
use crate::detections::configs;
|
||||||
use crate::detections::print;
|
use crate::detections::print;
|
||||||
use crate::detections::print::AlertMessage;
|
use crate::detections::print::{AlertMessage, IS_HIDE_RECORD_ID};
|
||||||
use crate::detections::utils;
|
use crate::detections::utils;
|
||||||
use crate::detections::utils::write_color_buffer;
|
use crate::detections::utils::write_color_buffer;
|
||||||
use chrono::{DateTime, Local, TimeZone, Utc};
|
use chrono::{DateTime, Local, TimeZone, Utc};
|
||||||
@@ -29,10 +29,10 @@ pub struct CsvFormat<'a> {
|
|||||||
event_i_d: &'a str,
|
event_i_d: &'a str,
|
||||||
level: &'a str,
|
level: &'a str,
|
||||||
mitre_attack: &'a str,
|
mitre_attack: &'a str,
|
||||||
rule_title: &'a str,
|
|
||||||
details: &'a str,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
record_i_d: Option<&'a str>,
|
record_i_d: Option<&'a str>,
|
||||||
|
rule_title: &'a str,
|
||||||
|
details: &'a str,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
record_information: Option<&'a str>,
|
record_information: Option<&'a str>,
|
||||||
rule_path: &'a str,
|
rule_path: &'a str,
|
||||||
@@ -47,10 +47,10 @@ pub struct DisplayFormat<'a> {
|
|||||||
pub channel: &'a str,
|
pub channel: &'a str,
|
||||||
pub event_i_d: &'a str,
|
pub event_i_d: &'a str,
|
||||||
pub level: &'a str,
|
pub level: &'a str,
|
||||||
pub rule_title: &'a str,
|
|
||||||
pub details: &'a str,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
record_i_d: Option<&'a str>,
|
record_i_d: Option<&'a str>,
|
||||||
|
pub rule_title: &'a str,
|
||||||
|
pub details: &'a str,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub record_information: Option<&'a str>,
|
pub record_information: Option<&'a str>,
|
||||||
}
|
}
|
||||||
@@ -217,6 +217,13 @@ fn emit_csv<W: std::io::Write>(
|
|||||||
"informational",
|
"informational",
|
||||||
"undefined",
|
"undefined",
|
||||||
]);
|
]);
|
||||||
|
let level_abbr: HashMap<String, String> = HashMap::from([
|
||||||
|
(String::from("cruitical"), String::from("crit")),
|
||||||
|
(String::from("high"), String::from("high")),
|
||||||
|
(String::from("medium"), String::from("med ")),
|
||||||
|
(String::from("low"), String::from("low ")),
|
||||||
|
(String::from("informational"), String::from("info")),
|
||||||
|
]);
|
||||||
// レベル別、日ごとの集計用変数の初期化
|
// レベル別、日ごとの集計用変数の初期化
|
||||||
for level_init in levels {
|
for level_init in levels {
|
||||||
detect_counts_by_date_and_level.insert(level_init.to_string(), HashMap::new());
|
detect_counts_by_date_and_level.insert(level_init.to_string(), HashMap::new());
|
||||||
@@ -233,10 +240,7 @@ fn emit_csv<W: std::io::Write>(
|
|||||||
timestamps.push(_get_timestamp(time));
|
timestamps.push(_get_timestamp(time));
|
||||||
for detect_info in detect_infos {
|
for detect_info in detect_infos {
|
||||||
detected_record_idset.insert(format!("{}_{}", time, detect_info.eventid));
|
detected_record_idset.insert(format!("{}_{}", time, detect_info.eventid));
|
||||||
let mut level = detect_info.level.to_string();
|
let level = detect_info.level.to_string();
|
||||||
if level == "informational" {
|
|
||||||
level = "info".to_string();
|
|
||||||
}
|
|
||||||
let time_str = format_time(time, false);
|
let time_str = format_time(time, false);
|
||||||
if displayflag {
|
if displayflag {
|
||||||
let record_id = detect_info
|
let record_id = detect_info
|
||||||
@@ -247,15 +251,24 @@ fn emit_csv<W: std::io::Write>(
|
|||||||
.record_information
|
.record_information
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|recinfo| _format_cellpos(recinfo, ColPos::Last));
|
.map(|recinfo| _format_cellpos(recinfo, ColPos::Last));
|
||||||
let details = detect_info
|
let ctr_char_exclude_details = detect_info
|
||||||
.detail
|
.detail
|
||||||
.chars()
|
.chars()
|
||||||
.filter(|&c| !c.is_control())
|
.filter(|&c| !c.is_control())
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
let dispformat = DisplayFormat {
|
let details = if ctr_char_exclude_details.is_empty() {
|
||||||
|
"-".to_string()
|
||||||
|
} else {
|
||||||
|
ctr_char_exclude_details
|
||||||
|
};
|
||||||
|
|
||||||
|
let dispformat: _ = DisplayFormat {
|
||||||
timestamp: &_format_cellpos(&time_str, ColPos::First),
|
timestamp: &_format_cellpos(&time_str, ColPos::First),
|
||||||
level: &_format_cellpos(&level, ColPos::Other),
|
level: &_format_cellpos(
|
||||||
|
level_abbr.get(&level).unwrap_or(&level),
|
||||||
|
ColPos::Other,
|
||||||
|
),
|
||||||
computer: &_format_cellpos(&detect_info.computername, ColPos::Other),
|
computer: &_format_cellpos(&detect_info.computername, ColPos::Other),
|
||||||
event_i_d: &_format_cellpos(&detect_info.eventid, ColPos::Other),
|
event_i_d: &_format_cellpos(&detect_info.eventid, ColPos::Other),
|
||||||
channel: &_format_cellpos(&detect_info.channel, ColPos::Other),
|
channel: &_format_cellpos(&detect_info.channel, ColPos::Other),
|
||||||
@@ -285,7 +298,7 @@ fn emit_csv<W: std::io::Write>(
|
|||||||
// csv output format
|
// csv output format
|
||||||
wtr.serialize(CsvFormat {
|
wtr.serialize(CsvFormat {
|
||||||
timestamp: &time_str,
|
timestamp: &time_str,
|
||||||
level: &level,
|
level: level_abbr.get(&level).unwrap_or(&level).trim(),
|
||||||
computer: &detect_info.computername,
|
computer: &detect_info.computername,
|
||||||
event_i_d: &detect_info.eventid,
|
event_i_d: &detect_info.eventid,
|
||||||
channel: &detect_info.channel,
|
channel: &detect_info.channel,
|
||||||
@@ -423,11 +436,10 @@ fn _get_serialized_disp_output(dispformat: Option<DisplayFormat>) -> String {
|
|||||||
"RuleTitle",
|
"RuleTitle",
|
||||||
"Details",
|
"Details",
|
||||||
];
|
];
|
||||||
let arg_match = &configs::CONFIG.read().unwrap().args;
|
if !*IS_HIDE_RECORD_ID {
|
||||||
if arg_match.is_present("display-record-id") {
|
titles.insert(5, "RecordID");
|
||||||
titles.push("RecordID");
|
|
||||||
}
|
}
|
||||||
if arg_match.is_present("full-data") {
|
if configs::CONFIG.read().unwrap().args.is_present("full-data") {
|
||||||
titles.push("RecordInformation");
|
titles.push("RecordInformation");
|
||||||
}
|
}
|
||||||
return format!("{}\n", titles.join("|"));
|
return format!("{}\n", titles.join("|"));
|
||||||
@@ -725,7 +737,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let expect_tz = expect_time.with_timezone(&Local);
|
let expect_tz = expect_time.with_timezone(&Local);
|
||||||
let expect =
|
let expect =
|
||||||
"Timestamp,Computer,Channel,EventID,Level,MitreAttack,RuleTitle,Details,RecordID,RecordInformation,RulePath,FilePath\n"
|
"Timestamp,Computer,Channel,EventID,Level,MitreAttack,RecordID,RuleTitle,Details,RecordInformation,RulePath,FilePath\n"
|
||||||
.to_string()
|
.to_string()
|
||||||
+ &expect_tz
|
+ &expect_tz
|
||||||
.clone()
|
.clone()
|
||||||
@@ -742,12 +754,12 @@ mod tests {
|
|||||||
+ ","
|
+ ","
|
||||||
+ test_attack
|
+ test_attack
|
||||||
+ ","
|
+ ","
|
||||||
|
+ test_record_id
|
||||||
|
+ ","
|
||||||
+ test_title
|
+ test_title
|
||||||
+ ","
|
+ ","
|
||||||
+ output
|
+ output
|
||||||
+ ","
|
+ ","
|
||||||
+ test_record_id
|
|
||||||
+ ","
|
|
||||||
+ test_recinfo
|
+ test_recinfo
|
||||||
+ ","
|
+ ","
|
||||||
+ test_rulepath
|
+ test_rulepath
|
||||||
@@ -779,7 +791,7 @@ mod tests {
|
|||||||
let test_timestamp = Utc
|
let test_timestamp = 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_header = "Timestamp|Computer|Channel|EventID|Level|RuleTitle|Details\n";
|
let expect_header = "Timestamp|Computer|Channel|EventID|Level|RecordID|RuleTitle|Details\n";
|
||||||
let expect_tz = test_timestamp.with_timezone(&Local);
|
let expect_tz = test_timestamp.with_timezone(&Local);
|
||||||
|
|
||||||
let expect_no_header = expect_tz
|
let expect_no_header = expect_tz
|
||||||
@@ -795,12 +807,12 @@ mod tests {
|
|||||||
+ "|"
|
+ "|"
|
||||||
+ test_level
|
+ test_level
|
||||||
+ "|"
|
+ "|"
|
||||||
|
+ test_recid
|
||||||
|
+ "|"
|
||||||
+ test_title
|
+ test_title
|
||||||
+ "|"
|
+ "|"
|
||||||
+ output
|
+ output
|
||||||
+ "|"
|
+ "|"
|
||||||
+ test_recid
|
|
||||||
+ "|"
|
|
||||||
+ test_recinfo
|
+ test_recinfo
|
||||||
+ "\n";
|
+ "\n";
|
||||||
assert_eq!(_get_serialized_disp_output(None,), expect_header);
|
assert_eq!(_get_serialized_disp_output(None,), expect_header);
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ fn build_app<'a>() -> ArgMatches<'a> {
|
|||||||
-C, --config [RULE_CONFIG_DIRECTORY] 'Rule config folder. (Default: .\\rules\\config)'
|
-C, --config [RULE_CONFIG_DIRECTORY] 'Rule config folder. (Default: .\\rules\\config)'
|
||||||
-o, --output [CSV_TIMELINE] 'Save the timeline in CSV format. (Ex: results.csv)'
|
-o, --output [CSV_TIMELINE] 'Save the timeline in CSV format. (Ex: results.csv)'
|
||||||
--all-tags 'Output all tags when saving to a CSV file.'
|
--all-tags 'Output all tags when saving to a CSV file.'
|
||||||
-R, --display-record-id 'Display event record ID.'
|
-R, --hide-record-id 'Do not display EventRecordID number.'
|
||||||
-v, --verbose 'Output verbose information.'
|
-v, --verbose 'Output verbose information.'
|
||||||
-V, --visualize-timeline 'Output event frequency timeline.'
|
-V, --visualize-timeline 'Output event frequency timeline.'
|
||||||
-D, --enable-deprecated-rules 'Enable rules marked as deprecated.'
|
-D, --enable-deprecated-rules 'Enable rules marked as deprecated.'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::detections::print::MESSAGES;
|
|||||||
use crate::detections::print::PIVOT_KEYWORD_LIST_FLAG;
|
use crate::detections::print::PIVOT_KEYWORD_LIST_FLAG;
|
||||||
use crate::detections::print::QUIET_ERRORS_FLAG;
|
use crate::detections::print::QUIET_ERRORS_FLAG;
|
||||||
use crate::detections::print::STATISTICS_FLAG;
|
use crate::detections::print::STATISTICS_FLAG;
|
||||||
use crate::detections::print::{CH_CONFIG, IS_DISPLAY_RECORD_ID, TAGS_CONFIG};
|
use crate::detections::print::{CH_CONFIG, IS_HIDE_RECORD_ID, TAGS_CONFIG};
|
||||||
use crate::detections::rule;
|
use crate::detections::rule;
|
||||||
use crate::detections::rule::AggResult;
|
use crate::detections::rule::AggResult;
|
||||||
use crate::detections::rule::RuleNode;
|
use crate::detections::rule::RuleNode;
|
||||||
@@ -233,7 +233,7 @@ impl Detection {
|
|||||||
.record_information
|
.record_information
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|recinfo| recinfo.to_string());
|
.map(|recinfo| recinfo.to_string());
|
||||||
let rec_id = if *IS_DISPLAY_RECORD_ID {
|
let rec_id = if !*IS_HIDE_RECORD_ID {
|
||||||
Some(
|
Some(
|
||||||
get_serde_number_to_string(&record_info.record["Event"]["System"]["EventRecordID"])
|
get_serde_number_to_string(&record_info.record["Event"]["System"]["EventRecordID"])
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
@@ -281,7 +281,7 @@ impl Detection {
|
|||||||
} else {
|
} else {
|
||||||
Option::None
|
Option::None
|
||||||
};
|
};
|
||||||
let rec_id = if *IS_DISPLAY_RECORD_ID {
|
let rec_id = if !*IS_HIDE_RECORD_ID {
|
||||||
Some(String::default())
|
Some(String::default())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -79,11 +79,11 @@ lazy_static! {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.args
|
.args
|
||||||
.is_present("pivot-keywords-list");
|
.is_present("pivot-keywords-list");
|
||||||
pub static ref IS_DISPLAY_RECORD_ID: bool = configs::CONFIG
|
pub static ref IS_HIDE_RECORD_ID: bool = configs::CONFIG
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.args
|
.args
|
||||||
.is_present("display-record-id");
|
.is_present("hide-record-id");
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Message {
|
impl Default for Message {
|
||||||
|
|||||||
Reference in New Issue
Block a user