Skip to content
Open
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
3 changes: 3 additions & 0 deletions ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@ func searchToAST(node interface{}) (SearchExpr, error) {
case n.Identifer != nil:
return SearchIdentifier{Name: *n.Identifer}, nil

case n.Pattern != nil:
return OneOfPattern{Pattern: *n.Pattern}, nil

case n.Subexpression != nil:
return searchToAST(*n.Subexpression)

Expand Down
2 changes: 1 addition & 1 deletion condition_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

var (
searchExprLexer = lexer.Must(lexer.Regexp(`(?P<Keyword>(?i)(1 of them)|(all of them)|(1 of)|(all of))` +
`|(?P<SearchIdentifierPattern>\*?[a-zA-Z_]+\*[a-zA-Z0-9_*]*)` +
`|(?P<SearchIdentifierPattern>\*?[a-zA-Z0-9_]+\*[a-zA-Z0-9_*]*)` +
`|(?P<SearchIdentifier>[a-zA-Z_][a-zA-Z0-9_]*)` +
`|(?P<Operator>(?i)and|or|not|[()])` + // TODO: this never actually matches anything because they get matched as a SearchIdentifier instead. However this isn't currently a problem because we don't parse anything in the Grammar as an Operator (we just use string constants which don't care about Operator vs SearchIdentifier)
`|(?P<ComparisonOperation>=|!=|<=|>=|<|>)` +
Expand Down
1 change: 1 addition & 0 deletions condition_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func TestParseCondition(t *testing.T) {
{"a and b and c", Condition{Search: And{SearchIdentifier{"a"}, SearchIdentifier{"b"}, SearchIdentifier{"c"}}}},
{"a | count(b) > 0", Condition{Search: SearchIdentifier{"a"}, Aggregation: Comparison{Func: Count{Field: "b"}, Op: GreaterThan, Threshold: 0}}},
{"a | count(b) >= 0", Condition{Search: SearchIdentifier{"a"}, Aggregation: Comparison{Func: Count{Field: "b"}, Op: GreaterThanEqual, Threshold: 0}}},
{"selection1*", Condition{Search: OneOfPattern{Pattern: "selection1*"}}},
{"note and pad", Condition{Search: And{SearchIdentifier{"note"}, SearchIdentifier{"pad"}}}},
}

Expand Down
1 change: 1 addition & 0 deletions internal/grammar/search_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Term struct {
Negated *Term `"not" @@`
OneAllOf *OneAllOf `| @@`
Identifer *string `| @SearchIdentifier`
Pattern *string `| @SearchIdentifierPattern`
Subexpression *Disjunction `| "(" @@ ")"`
}

Expand Down
30 changes: 30 additions & 0 deletions testdata/proxy_apt40_with_regex_in_condition.rule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
title: APT40 Dropbox Tool User Agent with digits in detection
id: 5ba715b6-71b7-44fd-8245-f66893e81b3d
status: experimental
description: Detects suspicious user agent string of APT40 Dropbox tool
references:
- Internal research from Florian Roth
author: Thomas Patzke
date: 2019/11/12
modified: 2020/09/02
tags:
- attack.command_and_control
- attack.t1071.001
- attack.t1043 # an old one
- attack.exfiltration
- attack.t1567.002
- attack.t1048 # an old one
logsource:
category: proxy
detection:
selection1_test:
c-useragent: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36'
selection1test:
r-dns: 'api.dropbox.com'
condition: selection1*
fields:
- c-ip
- c-uri
falsepositives:
- Old browsers
level: high