Skip to content

Commit

Permalink
Merge pull request #1463 from Yamato-Security/1433-v2-modifier-ge-lt-…
Browse files Browse the repository at this point in the history
…gte-lte

feat: add support v2 modifier(ge/gte/lt/lte)
  • Loading branch information
YamatoSecurity authored Oct 29, 2024
2 parents 0f4fc84 + 8832a22 commit 5973ffc
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 3 deletions.
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

0 comments on commit 5973ffc

Please sign in to comment.