Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support v2 modifier(ge/gte/lt/lte) #1463

Merged
merged 2 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG-Japanese.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## x.x.x [xxxx/xx/xx]

**新機能:**

- `gt`、`gte`、`lt`、`lte`のフィールドモディファイアに対応した。(#1433) (@fukusuket)

**バグ修正:**

- `csv-timeline`と`json-timeline`コマンドで、結果をターミナルに出力すると、プログレスバーの後にいくつかの結果が表示されていた。 (#1459) (@fukusuket)
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## x.x.x [xxxx/xx/xx]

**New Features:**

- Support for the `gt`, `gte`, `lt`, `lte` field modifiers. (#1433) (@fukusuket)

**Bug Fixes:**

- Some results would be displayed after the progress bar when outputting results to the terminal with `csv-timeline` and `json-timeline`. (#1459) (@fukusuket)
Expand Down
256 changes: 254 additions & 2 deletions src/detections/rule/matchers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,24 @@ impl LeafMatcher for DefaultMatcher {
| PipeElement::FieldRefContains(_)
| PipeElement::FieldRefEndswith(_)
| PipeElement::Endswithfield(_) => Some(pipe.is_eqfield_match(event_value, recinfo)),
PipeElement::Gt(_) | PipeElement::Lt(_) | PipeElement::Gte(_) | PipeElement::Lte(_) => {
let val = String::default();
let event_val_str = event_value.unwrap_or(&val);
let event_val_int = event_val_str.parse::<usize>();
match event_val_int {
Ok(event_val) => {
let cmp_result = match pipe {
PipeElement::Gt(n) => event_val > *n,
PipeElement::Lt(n) => event_val < *n,
PipeElement::Gte(n) => event_val >= *n,
PipeElement::Lte(n) => event_val <= *n,
_ => false,
};
Some(cmp_result)
}
Err(_) => Some(false), //数値以外のとき
}
}
_ => None,
};
if let Some(result) = match_result {
Expand Down Expand Up @@ -744,6 +762,10 @@ enum PipeElement {
All,
AllOnly,
Cased,
Gt(usize),
Lt(usize),
Gte(usize),
Lte(usize),
}

impl PipeElement {
Expand Down Expand Up @@ -772,13 +794,49 @@ impl PipeElement {
"all" => Some(PipeElement::All),
"allOnly" => Some(PipeElement::AllOnly),
"cased" => Some(PipeElement::Cased),
"gt" => match pattern.parse::<usize>() {
Ok(n) => Some(PipeElement::Gt(n)),
Err(_) => {
return Err(format!(
"gt value should be a number. key:{}",
utils::concat_selection_key(key_list)
))
}
},
"lt" => match pattern.parse::<usize>() {
Ok(n) => Some(PipeElement::Lt(n)),
Err(_) => {
return Err(format!(
"lt value should be a number. key:{}",
utils::concat_selection_key(key_list)
))
}
},
"gte" => match pattern.parse::<usize>() {
Ok(n) => Some(PipeElement::Gte(n)),
Err(_) => {
return Err(format!(
"gte value should be a number. key:{}",
utils::concat_selection_key(key_list)
))
}
},
"lte" => match pattern.parse::<usize>() {
Ok(n) => Some(PipeElement::Lte(n)),
Err(_) => {
return Err(format!(
"lte value should be a number. key:{}",
utils::concat_selection_key(key_list)
))
}
},
_ => None,
};

if let Some(elment) = pipe_element {
Result::Ok(elment)
Ok(elment)
} else {
Result::Err(format!(
Err(format!(
"An unknown pipe element was specified. key:{}",
utils::concat_selection_key(key_list)
))
Expand Down Expand Up @@ -3856,4 +3914,198 @@ mod tests {

check_select(rule_str, record_json_str, true);
}

#[test]
fn test_ge() {
let rule_str = r"
enabled: true
detection:
selection:
EventID|gt: 1040
condition: selection
";

let record_json_str = r#"
{
"Event": {
"System": {
"EventID": 1041
},
"EventData": {
"Data": "C:\\Windows\\hoge.exe"
}
}
}"#;

check_select(rule_str, record_json_str, true);
}

#[test]
fn test_ge_not() {
let rule_str = r"
enabled: true
detection:
selection:
EventID|gt: 1040
condition: selection
";

let record_json_str = r#"
{
"Event": {
"System": {
"EventID": 1040
},
"EventData": {
"Data": "C:\\Windows\\hoge.exe"
}
}
}"#;

check_select(rule_str, record_json_str, false);
}

#[test]
fn test_lt() {
let rule_str = r"
enabled: true
detection:
selection:
EventID|lt: 1040
condition: selection
";

let record_json_str = r#"
{
"Event": {
"System": {
"EventID": 1039
},
"EventData": {
"Data": "C:\\Windows\\hoge.exe"
}
}
}"#;

check_select(rule_str, record_json_str, true);
}
#[test]
fn test_lt_not() {
let rule_str = r"
enabled: true
detection:
selection:
EventID|lt: 1040
condition: selection
";

let record_json_str = r#"
{
"Event": {
"System": {
"EventID": 1040
},
"EventData": {
"Data": "C:\\Windows\\hoge.exe"
}
}
}"#;
check_select(rule_str, record_json_str, false);
}

#[test]
fn test_gte() {
let rule_str = r"
enabled: true
detection:
selection:
EventID|gte: 1040
condition: selection
";

let record_json_str = r#"
{
"Event": {
"System": {
"EventID": 1041
},
"EventData": {
"Data": "C:\\Windows\\hoge.exe"
}
}
}"#;

check_select(rule_str, record_json_str, true);
}
#[test]
fn test_gte_not() {
let rule_str = r"
enabled: true
detection:
selection:
EventID|gte: 1040
condition: selection
";

let record_json_str = r#"
{
"Event": {
"System": {
"EventID": 1039
},
"EventData": {
"Data": "C:\\Windows\\hoge.exe"
}
}
}"#;
check_select(rule_str, record_json_str, false);
}

#[test]
fn test_lte() {
let rule_str = r"
enabled: true
detection:
selection:
EventID|lte: 1040
condition: selection
";

let record_json_str = r#"
{
"Event": {
"System": {
"EventID": 1039
},
"EventData": {
"Data": "C:\\Windows\\hoge.exe"
}
}
}"#;

check_select(rule_str, record_json_str, true);
}
#[test]
fn test_lte_not() {
let rule_str = r"
enabled: true
detection:
selection:
EventID|lt: 1040
condition: selection
";

let record_json_str = r#"
{
"Event": {
"System": {
"EventID": 1041
},
"EventData": {
"Data": "C:\\Windows\\hoge.exe"
}
}
}"#;
check_select(rule_str, record_json_str, false);
}
}
6 changes: 5 additions & 1 deletion src/detections/rule/selectionnodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,11 @@ impl SelectionNode for LeafSelectionNode {
}

let mut event_value = self.get_event_value(event_record);
if self.get_key() == "EventID" && !self.select_value.is_null() {
if self.get_key() == "EventID"
&& !self.select_value.is_null()
&& !self.key_list.is_empty()
&& !self.key_list[0].contains("|")
{
if let Some(event_id) = self.select_value.as_i64() {
// 正規表現は重いので、数値のEventIDのみ文字列完全一致で判定
return event_value.unwrap_or(&String::default()) == &event_id.to_string();
Expand Down
Loading