]> git.ipfire.org Git - thirdparty/suricata-verify.git/commitdiff
tests: add rules testing with engine analysis
authorVictor Julien <victor@inliniac.net>
Fri, 17 Mar 2023 08:21:07 +0000 (09:21 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 17 Apr 2023 07:52:25 +0000 (09:52 +0200)
Tests check engine-analysis representation of rules.

14 files changed:
tests/rules/content/test.rules [new file with mode: 0644]
tests/rules/content/test.yaml [new file with mode: 0644]
tests/rules/dce_stub_data/test.rules [new file with mode: 0644]
tests/rules/dce_stub_data/test.yaml [new file with mode: 0644]
tests/rules/dns_query/test.rules [new file with mode: 0644]
tests/rules/dns_query/test.yaml [new file with mode: 0644]
tests/rules/file_data/test.rules [new file with mode: 0644]
tests/rules/file_data/test.yaml [new file with mode: 0644]
tests/rules/ftpbounce/test.rules [new file with mode: 0644]
tests/rules/ftpbounce/test.yaml [new file with mode: 0644]
tests/rules/http-header/test.rules [new file with mode: 0644]
tests/rules/http-header/test.yaml [new file with mode: 0644]
tests/rules/uricontent/test.rules [new file with mode: 0644]
tests/rules/uricontent/test.yaml [new file with mode: 0644]

diff --git a/tests/rules/content/test.rules b/tests/rules/content/test.rules
new file mode 100644 (file)
index 0000000..dfb7e27
--- /dev/null
@@ -0,0 +1,10 @@
+alert tcp any any -> any any (content:"one"; sid:1;)
+alert tcp any any -> any any (content:"one"; content:"two"; within:8; sid:2;)
+alert tcp any any -> any any (content:"one"; within:8; sid:3;)
+alert tcp any any -> any any (content:"one"; distance:8; sid:4;)
+alert smb any any -> any any (flow:to_server; pkt_data; content:"in pkt data"; sid:5;)
+#alert smb any any -> any any (flow:to_server; pcre:/one/R; sid:6;)
+alert smb any any -> any any (flow:to_server; pcre:/one/; sid:7;)
+#alert smb any any -> any any (flow:to_server; pcre:/one/RB; sid:8;)
+alert smb any any -> any any (flow:to_server; content:"one"; pcre:/two/R; sid:9;)
+alert tcp any any -> any any (content:"one"; distance:8; within:3; sid:10;)
diff --git a/tests/rules/content/test.yaml b/tests/rules/content/test.yaml
new file mode 100644 (file)
index 0000000..b011db7
--- /dev/null
@@ -0,0 +1,82 @@
+requires:
+    min-version: 7.0.0
+    pcap: false
+
+args:
+    - --engine-analysis
+
+checks:
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 1
+      mpm.buffer: "payload"
+      mpm.pattern: "one"
+      lists.payload.matches[0].name: "content"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 2
+      mpm.buffer: "payload"
+      mpm.pattern: "one"
+      lists.payload.matches[0].name: "content"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 3
+      mpm.buffer: "payload"
+      mpm.pattern: "one"
+      lists.payload.matches[0].name: "content"
+      lists.payload.matches[0].content.depth: 8
+      notes[0]: "'within' option for pattern w/o previous content was converted to 'depth'"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 4
+      mpm.buffer: "payload"
+      mpm.pattern: "one"
+      lists.payload.matches[0].name: "content"
+      lists.payload.matches[0].content.offset: 8
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 5
+      mpm.buffer: "payload"
+      mpm.pattern: "in|20|pkt|20|data"
+      lists.payload.matches[0].name: "content"
+      lists.payload.matches[0].content.pattern: "in|20|pkt|20|data"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 7
+      lists.payload.matches[0].name: "pcre"
+      lists.payload.matches[0].pcre.relative: false
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 9
+      mpm.buffer: "payload"
+      mpm.pattern: "one"
+      lists.payload.matches[0].name: "content"
+      lists.payload.matches[0].content.pattern: "one"
+      lists.payload.matches[0].content.relative_next: true
+      lists.payload.matches[1].name: "pcre"
+      lists.payload.matches[1].pcre.relative: true
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 10
+      mpm.buffer: "payload"
+      mpm.pattern: "one"
+      lists.payload.matches[0].name: "content"
+      lists.payload.matches[0].content.offset: 8
+      lists.payload.matches[0].content.depth: 11
+      notes[0]: "'within' option for pattern w/o previous content was converted to 'depth'"
diff --git a/tests/rules/dce_stub_data/test.rules b/tests/rules/dce_stub_data/test.rules
new file mode 100644 (file)
index 0000000..41a35ac
--- /dev/null
@@ -0,0 +1,23 @@
+alert tcp any any -> any any (dce_stub_data; content:"one"; sid:1;)
+alert tcp any any -> any any (dcerpc.stub_data; content:"one"; content:"two"; within:8; sid:2;)
+alert tcp any any -> any any (dce_stub_data; content:"1"; fast_pattern; content:"two"; sid:3;)
+alert tcp any any -> any any (dcerpc.stub_data; content:"one"; pcre:/two/R; sid:4;)
+
+alert tcp any any -> any any (dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; dce_stub_data; content:"one"; fast_pattern; distance:0; isdataat:4,relative; sid:5;)
+# TODO check if rawbytes makes sense here. Was in unittest.
+alert tcp any any -> any any (dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; dce_stub_data; content:"one"; distance:0; isdataat:4,relative,rawbytes; sid:6;)
+
+alert dcerpc any any -> any any (flow:to_server; dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; dce_stub_data; pcre:/one/R; sid:7;)
+
+
+alert smb any any -> any any (flow:to_server; dce_stub_data; content:"one"; distance:10; within:5; content:"two"; within:5; pkt_data; content:"three"; content:"four"; sid:8;)
+
+alert tcp any any -> any any (pcre:/one/; content:"two"; distance:10; within:5; content:"three"; within:5;content:"four";content:"five"; sid:9;)
+alert tcp any any -> any any (byte_jump:2,5; pcre:/one/; content:"two"; distance:10; within:5; content:"three"; within:5;content:"four";content:"five"; sid:10;)
+alert tcp any any -> any any (byte_jump:2,5,relative; pcre:/one/; content:"two"; distance:10; within:5; content:"three"; within:5;content:"four";content:"five"; sid:11;)
+
+alert tcp any any -> any any (content:"one"; byte_jump:1,2,relative,align,dce; content:"two"; within:4; sid:12;)
+
+alert smb any any -> any any (flow:to_server; dce_stub_data; byte_test:1,=,0,0,relative,dce; sid:13;)
+
+alert tcp any any -> any any (dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; dce_stub_data; content:"one"; distance:0; isdataat:4,relative; sid:14;)
diff --git a/tests/rules/dce_stub_data/test.yaml b/tests/rules/dce_stub_data/test.yaml
new file mode 100644 (file)
index 0000000..9ec1cea
--- /dev/null
@@ -0,0 +1,195 @@
+requires:
+    min-version: 7.0.0
+    pcap: false
+
+args:
+    - --engine-analysis
+
+checks:
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 1
+      mpm.buffer: "dce_stub_data"
+      mpm.pattern: "one"
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[0].name: "content"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 2
+      mpm.buffer: "dce_stub_data"
+      mpm.pattern: "one"
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.within: 8
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 3
+      mpm.buffer: "dce_stub_data"
+      mpm.pattern: "1"
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.pattern: "1"
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.pattern: "two"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 4
+      mpm.buffer: "dce_stub_data"
+      mpm.pattern: "one"
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "pcre"
+      engines[0].matches[1].pcre.relative: true
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 5
+      mpm.buffer: "dce_stub_data"
+      mpm.pattern: "one"
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.pattern: "one"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "isdataat"
+      engines[1].name: "dce_stub_data"
+      engines[2].name: "dce_stub_data"
+      engines[3].name: "dce_stub_data"
+      engines[4].name: "dce_generic"
+      engines[4].matches[0].name: "dcerpc.iface"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 7
+      engines[0].name: "dce_generic"
+      engines[0].app_proto: "dcerpc"
+      engines[0].matches[0].name: "dcerpc.iface"
+      engines[1].name: "dce_generic"
+      engines[1].app_proto: "smb"
+      engines[1].matches[0].name: "dcerpc.iface"
+      # bug 5902: we get smb engines despite "alert dcerpc"
+      engines[2].name: "dce_stub_data"
+      engines[2].matches[0].name: "pcre"
+      engines[2].matches[0].pcre.relative: true
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 8
+      mpm.buffer: "dce_stub_data"
+      mpm.pattern: "one"
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.pattern: "one"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.pattern: "two"
+      engines[0].matches[1].content.relative_next: false
+      engines[1].name: "stream"
+      engines[1].matches[0].name: "content"
+      engines[1].matches[0].content.pattern: "three"
+      engines[1].matches[0].content.relative_next: false
+      engines[1].matches[1].name: "content"
+      engines[1].matches[1].content.pattern: "four"
+      engines[1].matches[1].content.relative_next: false
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 9
+      mpm.buffer: "payload"
+      mpm.pattern: "three"
+      lists.payload.matches[0].name: "pcre"
+      lists.payload.matches[1].name: "content"
+      lists.payload.matches[2].name: "content"
+      lists.payload.matches[3].name: "content"
+      lists.payload.matches[4].name: "content"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 10
+      mpm.buffer: "payload"
+      mpm.pattern: "three"
+      lists.payload.matches[0].name: "byte_jump"
+      lists.payload.matches[0].byte_jump.nbytes: 2
+      lists.payload.matches[0].byte_jump.offset: 5
+      lists.payload.matches[1].name: "pcre"
+      lists.payload.matches[1].pcre.relative: false
+      lists.payload.matches[2].name: "content"
+      lists.payload.matches[3].name: "content"
+      lists.payload.matches[4].name: "content"
+      lists.payload.matches[5].name: "content"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 11
+      mpm.buffer: "payload"
+      mpm.pattern: "three"
+      lists.payload.matches[0].name: "byte_jump"
+      lists.payload.matches[0].byte_jump.nbytes: 2
+      lists.payload.matches[0].byte_jump.offset: 5
+      lists.payload.matches[0].byte_jump.flags[0]: "relative"
+      lists.payload.matches[1].name: "pcre"
+      lists.payload.matches[1].pcre.relative: false
+      lists.payload.matches[2].name: "content"
+      lists.payload.matches[3].name: "content"
+      lists.payload.matches[4].name: "content"
+      lists.payload.matches[5].name: "content"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 12
+      mpm.buffer: "payload"
+      mpm.pattern: "one"
+      lists.payload.matches[0].name: "content"
+      lists.payload.matches[1].name: "byte_jump"
+      lists.payload.matches[1].byte_jump.nbytes: 1
+      lists.payload.matches[1].byte_jump.offset: 2
+      lists.payload.matches[1].byte_jump.flags[0]: "relative"
+      lists.payload.matches[1].byte_jump.flags[1]: "align"
+      lists.payload.matches[1].byte_jump.flags[2]: "dce"
+      lists.payload.matches[2].name: "content"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 13
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[0].name: "byte_test"
+      engines[0].matches[0].byte_test.nbytes: 1
+      engines[0].matches[0].byte_test.offset: 0
+      engines[0].matches[0].byte_test.flags[0]: "relative"
+      engines[0].matches[0].byte_test.flags[1]: "dce"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 14
+      mpm.buffer: "dce_stub_data"
+      mpm.pattern: "one"
+      engines[0].name: "dce_stub_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.pattern: "one"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "isdataat"
+      engines[1].name: "dce_stub_data"
+      engines[2].name: "dce_stub_data"
+      engines[3].name: "dce_stub_data"
+      engines[4].name: "dce_generic"
+      engines[4].matches[0].name: "dcerpc.iface"
diff --git a/tests/rules/dns_query/test.rules b/tests/rules/dns_query/test.rules
new file mode 100644 (file)
index 0000000..245dbda
--- /dev/null
@@ -0,0 +1 @@
+alert dns any any -> any any (dns_query; content:"one"; isdataat:!4,relative; sid:1;)
diff --git a/tests/rules/dns_query/test.yaml b/tests/rules/dns_query/test.yaml
new file mode 100644 (file)
index 0000000..9889436
--- /dev/null
@@ -0,0 +1,19 @@
+requires:
+    min-version: 7.0.0
+    pcap: false
+
+args:
+    - --engine-analysis
+
+checks:
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 1
+      mpm.buffer: "dns_query"
+      mpm.pattern: "one"
+      engines[0].name: "dns_query"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "isdataat"
diff --git a/tests/rules/file_data/test.rules b/tests/rules/file_data/test.rules
new file mode 100644 (file)
index 0000000..becf2dd
--- /dev/null
@@ -0,0 +1,9 @@
+alert tcp any any -> any any (file.data; content:"one"; sid:1;)
+alert tcp any any -> any any (file.data; content:"one"; content:"two"; within:8; sid:2;)
+alert tcp any any -> any any (file.data; content:"one"; within:8; sid:3;)
+alert tcp any any -> any any (file.data; content:"one"; distance:8; sid:4;)
+alert smb any any -> any any (flow:to_server; file_data; content:"in file data"; pkt_data; content:"in pkt data"; sid:5;)
+alert smb any any -> any any (flow:to_server; file.data; pcre:/one/R; sid:6;)
+alert smb any any -> any any (flow:to_server; file.data; pcre:/one/; sid:7;)
+alert smb any any -> any any (flow:to_server; file.data; pcre:/one/RB; sid:8;)
+alert smb any any -> any any (flow:to_server; file.data; content:"one"; pcre:/two/R; sid:9;)
diff --git a/tests/rules/file_data/test.yaml b/tests/rules/file_data/test.yaml
new file mode 100644 (file)
index 0000000..2810325
--- /dev/null
@@ -0,0 +1,107 @@
+requires:
+    min-version: 7.0.0
+    pcap: false
+
+args:
+    - --engine-analysis
+
+checks:
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 1
+      mpm.buffer: "file_data"
+      mpm.pattern: "one"
+      engines[0].name: "file_data"
+      engines[0].matches[0].name: "content"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 2
+      mpm.buffer: "file_data"
+      mpm.pattern: "one"
+      engines[0].name: "file_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].name: "file_data"
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.within: 8
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 3
+      mpm.buffer: "file_data"
+      mpm.pattern: "one"
+      engines[0].name: "file_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.depth: 8
+      notes[0]: "'within' option for pattern w/o previous content was converted to 'depth'"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 4
+      mpm.buffer: "file_data"
+      mpm.pattern: "one"
+      engines[0].name: "file_data"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.offset: 8
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 5
+      mpm.buffer: "file_data"
+      mpm.pattern: "in|20|file|20|data"
+      engines[0].name: "file_data"
+      engines[0].direction: "toserver"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.pattern: "in|20|file|20|data"
+      engines[1].name: "stream"
+      engines[1].direction: "toserver"
+      engines[1].matches[0].name: "content"
+      engines[1].matches[0].content.pattern: "in|20|pkt|20|data"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 6
+      engines[0].name: "file_data"
+      engines[0].direction: "toserver"
+      engines[0].matches[0].name: "pcre"
+      engines[0].matches[0].pcre.relative: true
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 7
+      engines[0].name: "file_data"
+      engines[0].direction: "toserver"
+      engines[0].matches[0].name: "pcre"
+      engines[0].matches[0].pcre.relative: false
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 8
+      engines[0].name: "file_data"
+      engines[0].direction: "toserver"
+      engines[0].matches[0].name: "pcre"
+      engines[0].matches[0].pcre.relative: true
+      notes[0]: "'/B' (rawbytes) option is a no-op and is silently ignored"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 9
+      mpm.buffer: "file_data"
+      mpm.pattern: "one"
+      engines[0].name: "file_data"
+      engines[0].direction: "toserver"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.pattern: "one"
+      engines[0].matches[1].name: "pcre"
+      engines[0].matches[1].pcre.relative: true
diff --git a/tests/rules/ftpbounce/test.rules b/tests/rules/ftpbounce/test.rules
new file mode 100644 (file)
index 0000000..1a9d211
--- /dev/null
@@ -0,0 +1 @@
+alert tcp any any -> any any (ftpbounce; sid:1;)
diff --git a/tests/rules/ftpbounce/test.yaml b/tests/rules/ftpbounce/test.yaml
new file mode 100644 (file)
index 0000000..5c81308
--- /dev/null
@@ -0,0 +1,16 @@
+requires:
+    min-version: 7.0.0
+    pcap: false
+
+args:
+    - --engine-analysis
+
+checks:
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 1
+      engines[0].name: "ftp_request"
+      engines[0].direction: "toserver"
+      engines[0].matches[0].name: "ftpbounce"
diff --git a/tests/rules/http-header/test.rules b/tests/rules/http-header/test.rules
new file mode 100644 (file)
index 0000000..bb0b0c3
--- /dev/null
@@ -0,0 +1,17 @@
+alert tcp any any -> any any (content:"one"; http_header; sid:1;)
+alert tcp any any -> any any (pcre:/one/H; content:"two"; within:5; http_header; sid:2;)
+alert tcp any any -> any any (content:"one"; http_header; content:"two"; distance:0; http_header; sid:3;)
+alert tcp any any -> any any (content:"one"; http_header; content:"two"; http_header; distance:0; sid:4;)
+alert tcp any any -> any any (content:"one"; within:5; http_header; sid:5;)
+alert tcp any any -> any any (content:"one"; http_header; within:5; sid:6;)
+alert tcp any any -> any any (content:"one"; http_header; pcre:/two/HR; sid:7;)
+alert tcp any any -> any any (pcre:/one/H; content:"two"; distance:5; http_header; sid:8;)
+alert tcp any any -> any any (content:"one"; http_header; content:"two"; http_header; distance:0; content:"three"; http_header; distance:0; content:"four"; http_header; distance:0; sid:9;)
+alert tcp any any -> any any (content:"one"; http_header; isdataat:!1,relative; sid:10;)
+alert tcp any any -> any any (content:"one"; http_header; content:"two"; sid:11;)
+alert tcp any any -> any any (flow:to_server; content:"one"; http_header; content:"two"; sid:12;)
+alert tcp any any -> any any (flow:to_server; content:"1"; fast_pattern; http_header; content:"two"; http_header; sid:13;)
+alert tcp any any -> any any (flow:to_server; content:"1"; fast_pattern; http_header; base64_decode:bytes 16; base64_data; content:"two"; sid:14;)
+# TODO should be rejected?
+#alert tcp any any -> any any (flow:to_server; content:"1"; fast_pattern; http_header; base64_decode; content:"two"; sid:15;)
+alert tcp any any -> any any (content:"one"; http_header; isdataat:!4,relative; sid:16;)
diff --git a/tests/rules/http-header/test.yaml b/tests/rules/http-header/test.yaml
new file mode 100644 (file)
index 0000000..d8231ba
--- /dev/null
@@ -0,0 +1,189 @@
+requires:
+    min-version: 7.0.0
+    pcap: false
+
+args:
+    - --engine-analysis
+
+checks:
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 1
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 2
+      mpm.buffer: "http_header"
+      mpm.pattern: "two"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "pcre"
+      engines[0].matches[0].pcre.relative_next: true
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.within: 5
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 3
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.distance: 0
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 4
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.distance: 0
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 5
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.depth: 5
+      notes[0]: "'within' option for pattern w/o previous content was converted to 'depth'"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 6
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.depth: 5
+      notes[0]: "'within' option for pattern w/o previous content was converted to 'depth'"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 7
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "pcre"
+      engines[0].matches[1].pcre.relative: true
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 8
+      mpm.buffer: "http_header"
+      mpm.pattern: "two"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "pcre"
+      engines[0].matches[0].pcre.relative_next: true
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.distance: 5
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 9
+      mpm.buffer: "http_header"
+      mpm.pattern: "three"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.distance: 0
+      engines[0].matches[1].content.relative_next: true
+      engines[0].matches[2].name: "content"
+      engines[0].matches[2].content.distance: 0
+      engines[0].matches[2].content.relative_next: true
+      engines[0].matches[3].name: "content"
+      engines[0].matches[3].content.distance: 0
+      engines[0].matches[3].content.relative_next: false
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 10
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: false
+      engines[0].matches[0].content.ends_with: true
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 11
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: false
+      engines[2].name: "stream"
+      engines[2].matches[0].name: "content"
+      engines[2].matches[0].content.relative_next: false
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 12
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: false
+      engines[1].name: "stream"
+      engines[1].matches[0].name: "content"
+      engines[1].matches[0].content.relative_next: false
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 13
+      mpm.buffer: "http_header"
+      mpm.pattern: "1"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: false
+      engines[0].matches[1].name: "content"
+      engines[0].matches[1].content.relative_next: false
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 14
+      mpm.buffer: "http_header"
+      mpm.pattern: "1"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: false
+      engines[0].matches[1].name: "base64_decode"
+      lists.base64_data.matches[0].name: "content"
+      lists.base64_data.matches[0].content.pattern: "two"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 16
+      mpm.buffer: "http_header"
+      mpm.pattern: "one"
+      engines[0].name: "http_header"
+      engines[0].matches[0].name: "content"
+      engines[0].matches[0].content.relative_next: true
+      engines[0].matches[1].name: "isdataat"
diff --git a/tests/rules/uricontent/test.rules b/tests/rules/uricontent/test.rules
new file mode 100644 (file)
index 0000000..d0d6a6e
--- /dev/null
@@ -0,0 +1 @@
+alert tcp any any -> any any (uricontent:"one"; sid:1;)
diff --git a/tests/rules/uricontent/test.yaml b/tests/rules/uricontent/test.yaml
new file mode 100644 (file)
index 0000000..0ccb948
--- /dev/null
@@ -0,0 +1,15 @@
+requires:
+    min-version: 7.0.0
+    pcap: false
+
+args:
+    - --engine-analysis
+
+checks:
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 1
+      mpm.buffer: "http_uri"
+      mpm.pattern: "one"