From 7f8ef6a0d7d4ad663cb2b10bf741a4844cf79313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Uh=C5=99=C3=AD=C4=8Dek?= Date: Sat, 15 Aug 2020 16:44:09 +0200 Subject: [PATCH] Handles escaped characters in parseContent. --- parser.go | 8 +++++++- parser_test.go | 33 +++++++++++++++++++++++++++++++++ rule_test.go | 13 ++++++++++--- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/parser.go b/parser.go index 8eb7434..9223dda 100644 --- a/parser.go +++ b/parser.go @@ -34,6 +34,9 @@ var hexRE = regexp.MustCompile(`(?i)(\|(?:\s*[a-f0-9]{2}\s*)+\|)`) // escapeRE matches char that needs to escaped in regexp. var escapeRE = regexp.MustCompile(`([()+.'\\])`) +// escapeContent matches escaped special characters. +var escapeContent = regexp.MustCompile(`\\([\\;":])`) + // metaSplitRE matches string in metadata var metaSplitRE = regexp.MustCompile(`,\s*`) @@ -48,7 +51,10 @@ func parseContent(content string) ([]byte, error) { errpanic = fmt.Errorf("recovered from panic: %v", r) } }() - b := hexRE.ReplaceAllStringFunc(content, + + b := escapeContent.ReplaceAllString(content, "$1") + + b = hexRE.ReplaceAllStringFunc(b, func(h string) string { r, err := hex.DecodeString(strings.Replace(strings.Trim(h, "|"), " ", "", -1)) if err != nil { diff --git a/parser_test.go b/parser_test.go index 73334b9..c6a167f 100644 --- a/parser_test.go +++ b/parser_test.go @@ -45,6 +45,16 @@ func TestParseContent(t *testing.T) { input: "A|7C|B", want: []byte("A|B"), }, + { + name: "contains escaped backslash", + input: `A\\B`, + want: []byte(`A\B`), + }, + { + name: "contains multiple escaped characters", + input: `A\\\;\"\\\:B`, + want: []byte(`A\;"\:B`), + }, } { got, err := parseContent(tt.input) if !reflect.DeepEqual(got, tt.want) || (err != nil) != tt.wantErr { @@ -1552,6 +1562,29 @@ func TestParseRule(t *testing.T) { }, }, }, + { + name: "content with escaped characters", + rule: `alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"escaped characters"; content:"A\\B\;C\"\:"; sid:7; rev:1;)`, want: &Rule{ + Action: "alert", + Protocol: "tcp", + Source: Network{ + Nets: []string{"$HOME_NET"}, + Ports: []string{"any"}, + }, + Destination: Network{ + Nets: []string{"$EXTERNAL_NET"}, + Ports: []string{"any"}, + }, + SID: 7, + Revision: 1, + Description: "escaped characters", + Matchers: []orderedMatcher{ + &Content{ + Pattern: []byte{0x41, 0x5c, 0x42, 0x3b, 0x43, 0x22, 0x3a}, + }, + }, + }, + }, { name: "content and pcre order matters", rule: `alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"check order"; content:"1"; pcre:"/this.*/R"; content:"2"; sid:1; rev:1;)`, want: &Rule{ diff --git a/rule_test.go b/rule_test.go index d679791..5daa44a 100644 --- a/rule_test.go +++ b/rule_test.go @@ -88,11 +88,11 @@ func TestContentFormatPattern(t *testing.T) { want: "abcd|3B 3A 0D 0A|e|0D|f", }, { - name: "double backslash", + name: "backslash", input: &Content{ - Pattern: []byte(`C:\\WINDOWS\\system32\\`), + Pattern: []byte(`C:\WINDOWS\system32\`), }, - want: `C|3A 5C 5C|WINDOWS|5C 5C|system32|5C 5C|`, + want: `C|3A 5C|WINDOWS|5C|system32|5C|`, }, { name: "content with hex pipe", @@ -101,6 +101,13 @@ func TestContentFormatPattern(t *testing.T) { }, want: `C|7C|B`, }, + { + name: "escaped characters", + input: &Content{ + Pattern: []byte(`A\B;C":`), + }, + want: `A|5C|B|3B|C|22 3A|`, + }, } { got := tt.input.FormatPattern() if !reflect.DeepEqual(got, tt.want) {