diff --git a/tests/datasets-cidr/README.md b/tests/datasets-cidr/README.md new file mode 100644 index 0000000000..6ccd12572b --- /dev/null +++ b/tests/datasets-cidr/README.md @@ -0,0 +1,282 @@ +# CIDR Dataset Tests + +This directory contains suricata-verify tests for the `cidr` dataset type. CIDR +datasets store IPv4 and IPv6 CIDR blocks in radix trees and are queried via the +`ip.src` or `ip.dst` sticky buffers using `dataset:isset` or `dataset:isnotset`. + +The dataset file format is plain text, one CIDR notation per line (e.g. +`192.168.0.0/16`, `fc00::/7`). + +## Test Overview + +Tests are grouped by what they exercise: + +- 01-10 -- basic type behavior (isset/isnotset for IPv4, IPv6, mixed, + host-exact precision, boundary conditions, empty dataset) +- 11-12 -- set/unset behavior on IPv4 +- 13-14, 22-26 -- rejection tests (options that must fail rule load) +- 15, 17-19 -- the `mask` option and its notations +- 16 -- Lua access to a CIDR dataset +- 20-21 -- set/unset behavior on IPv6 +- 27 -- CIDR-dataset equivalent of the luaxform IP->CIDR-string pattern + used by `tests/lua/lua-transform-09`, reusing that test's pcap and + assertions + +### datasets-cidr-01-ipv4-isset + +Basic IPv4 isset test. Five DNS packets are sent to 8.8.8.8 with varying source +IPs. The CIDR file `rfc1918.lst` contains the three RFC1918 blocks. Three source +addresses (192.168.1.5, 10.0.0.50, 172.17.0.1) fall within those blocks and +trigger sid:1. The remaining two (1.2.3.4, 203.0.113.1) are public and do not. + +Generates: `input-ipv4.pcap` (shared by tests 02, 03, 04, 08, 10) + +### datasets-cidr-02-ipv4-isnotset + +Inverts test 01. Uses `isnotset` so sid:1 fires for the two public source IPs +(1.2.3.4 and 203.0.113.1) that are not covered by `rfc1918.lst`. Reuses +`../datasets-cidr-01-ipv4-isset/input-ipv4.pcap`. + +### datasets-cidr-03-ipv4-dst + +Matches on `ip.dst` instead of `ip.src`. All five packets in the shared pcap +go to 8.8.8.8, which falls inside `8.8.0.0/16` as loaded from `google-dns.lst`. +All five packets trigger sid:1. Reuses `../datasets-cidr-01-ipv4-isset/input-ipv4.pcap`. + +### datasets-cidr-04-multi-rule + +Two rules reference the same dataset simultaneously. Sid:1 uses `ip.src` isset +and fires for the three RFC1918 source addresses. Sid:2 uses `ip.dst` isnotset +and fires for all five packets because 8.8.8.8 is a public address not covered +by the RFC1918 dataset. Total alert count is 8. Reuses the shared ipv4 pcap. + +### datasets-cidr-05-ipv6-isset + +Basic IPv6 isset test. Four DNS packets carry IPv6 source addresses. The CIDR +file `ula.lst` contains `fc00::/7`, which covers all ULA addresses. Both +`fc00::1` and `fd12:3456::1` fall within `fc00::/7`; `2001:db8::1` and +`fe80::1` do not. + +Generates: `input-ipv6.pcap` (shared by test 06) + +### datasets-cidr-06-ipv6-isnotset + +Inverts test 05. Uses `isnotset` so sid:1 fires for the two non-ULA source +addresses (2001:db8::1 and fe80::1). Reuses +`../datasets-cidr-05-ipv6-isset/input-ipv6.pcap`. + +### datasets-cidr-07-mixed + +A single CIDR file `mixed.lst` contains both an IPv4 block (`192.168.0.0/16`) +and an IPv6 block (`fc00::/7`). The pcap contains three packets: an IPv4 packet +from 192.168.1.5, an IPv6 packet from fc00::1, and an IPv4 packet from 1.2.3.4. +Only the first two match. + +Generates: `input-mixed.pcap` + +### datasets-cidr-08-host-exact + +Tests `/32` precision. The file `host32.lst` contains only `192.168.1.5/32`. +From the five-packet shared pcap, only the packet sourced from exactly +192.168.1.5 matches. The other two RFC1918 sources (10.0.0.50 and 172.17.0.1) +do not match despite being private addresses. Reuses the shared ipv4 pcap. + +### datasets-cidr-09-boundary + +Tests the exact boundary of `192.168.0.0/16`. Four packets probe the first +address of the range (192.168.0.0), the last address (192.168.255.255), one +address just above (192.169.0.1), and one address just below (192.167.255.255). +Sid:1 (isset) fires for the two in-range addresses; sid:2 (isnotset) fires for +the two out-of-range addresses. + +Generates: `input-boundary.pcap` + +### datasets-cidr-10-empty + +Tests behavior with an empty CIDR file. The `empty.lst` file contains no +entries. Sid:1 (isset) never fires because no IP can match an empty dataset. +Sid:2 (isnotset) fires for all five packets from the shared ipv4 pcap because +every IP is absent from the empty dataset. Reuses the shared ipv4 pcap. + +### datasets-cidr-11-set + +Basic `dataset:set` behavior on IPv4. Four packets from two unique sources +(1.2.3.4 and 5.6.7.8, two packets each). Sid:1 fires exactly once per +unique source: the first packet inserts a new /32 entry (`set` returns +match), the second packet finds it already present (`set` returns no +match). Total alert count is 2. + +Generates: `input.pcap` + +### datasets-cidr-12-unset + +Basic `dataset:unset` behavior on IPv4. `host.lst` preloads 1.2.3.4 and +5.6.7.8. Five packets: two from 1.2.3.4, two from 5.6.7.8, one from +9.9.9.9 (never in the set). Sid:1 fires on the first packet from each +preloaded source (the `unset` removes the entry); the second packet from +each source no longer matches. 9.9.9.9 never matches. Total 2 alerts. + +Generates: `input.pcap` + +### datasets-cidr-13-save-reject + +Rule uses the `save` option on a CIDR dataset. Rule load must fail with +`save/state is not supported for CIDR datasets`. Test runs +`--engine-analysis` (no pcap) and greps the log for that exact string; +requires `exit-code: 1`. + +### datasets-cidr-14-state-reject + +Same shape as 13, using the `state` option instead of `save`. Same +expected error message. + +### datasets-cidr-15-mask + +`dataset:set,type cidr,mask 24`. Four packets across two /24s: two +packets each from 192.168.1.5 and 192.168.2.1. With mask 24 the /24 +prefix (192.168.1.0/24, 192.168.2.0/24) is what gets inserted, so +sid:1 fires exactly once per unique /24. Packets are constructed with +the same 5-tuple within each /24 so autofp routes them to the same +worker, keeping ordering deterministic. + +Generates: `input.pcap` (shared by tests 17 and 18) + +### datasets-cidr-16-lua + +Two rules. Sid:1 is a standard CIDR `isset` against `rfc1918.lst` (via +`cidr.lst`). Sid:2 uses `lua:cidr-check.lua`; the Lua script calls +`dataset:get("rfc1918-cidr")` and returns 1 when the retrieval succeeds. +Uses `--set default-rule-path=.` so the Lua script is found relative to +the test directory rather than the system rules dir. Reuses the shared +`datasets-cidr-01-ipv4-isset/input-ipv4.pcap`. + +### datasets-cidr-17-mask-hex-prefix + +Hex-prefix form of the mask option: `mask 0x18` (== 24). Same rule and +expected behavior as test 15; reuses that test's `input.pcap`. Confirms +the parser accepts hex prefix lengths and treats them identically to +their decimal form. + +### datasets-cidr-18-mask-bitmask + +IPv4 bitmask form of the mask option: `mask 0xffffff00` (== /24). Same +rule shape and expected behavior as test 15; reuses that test's +`input.pcap`. Confirms the parser converts an IPv4 dotted-mask numeric +value to its prefix-length equivalent. + +### datasets-cidr-19-unset-mask + +`dataset:unset,type cidr,mask 24` with `cidr.lst` preloading two /24 +prefixes (192.168.1.0/24, 192.168.2.0/24). Four packets across those +two /24s (mirror of test 15's traffic pattern). Sid:1 fires exactly +once per /24 as the `unset` removes the netblock; subsequent packets in +the same /24 no longer match. + +Generates: `input.pcap` + +### datasets-cidr-20-ipv6-set + +IPv6 mirror of test 11. Four packets from two unique IPv6 sources +(fc00::1 and 2001:db8::1, two packets each). Sid:1 fires once per unique +source (the first packet inserts a new /128 entry; the second finds it +already present). Uses a per-test `suricata.yaml` with `ipv6-compress: +yes` so eve.json emits addresses in RFC 5952 compressed form to match +the `src_ip` filters in `test.yaml`. + +Generates: `input-ipv6.pcap` + +### datasets-cidr-21-ipv6-unset + +IPv6 mirror of test 12. `host.lst` preloads fc00::1 and 2001:db8::1. +Five packets: two from fc00::1, two from 2001:db8::1, one from fe80::1 +(never in the set). Sid:1 fires on the first packet from each preloaded +source; second packet from each source no longer matches; fe80::1 never +matches. Also uses `ipv6-compress: yes`. + +Generates: `input-ipv6.pcap` + +### datasets-cidr-22-mask-isset-reject + +Rule combines the `mask` option with `isset` on a CIDR dataset. Rule +load must fail with `mask is only supported for CIDR datasets with 'set' +and 'unset' commands`. `--engine-analysis`, no pcap, `exit-code: 1`. + +### datasets-cidr-23-mask-out-of-range + +Rule uses a non-contiguous IPv4 bitmask (`mask 0x00ff00ff`). Rule load +must fail with `not a contiguous IPv4 netmask`. `--engine-analysis`, +no pcap, `exit-code: 1`. + +### datasets-cidr-24-mask-non-cidr-reject + +Rule combines the `mask` option with `type ipv4` (a non-CIDR type). +Rule load must fail with `mask is only supported for CIDR datasets`. +`--engine-analysis`, no pcap, `exit-code: 1`. + +### datasets-cidr-25-datarep-cidr-reject + +Rule uses the `datarep` keyword with `type cidr`. Rule load must fail; +the datarep type parser doesn't accept `cidr`, so the signature is +rejected and the log contains `error parsing signature`. +`--engine-analysis`, no pcap, `exit-code: 1`. + +### datasets-cidr-26-mask-zero-reject + +Rule uses `mask 0` (which would match every address). Rule load must +fail with `prefix length 0 is not allowed`. `--engine-analysis`, no +pcap, `exit-code: 1`. + +### datasets-cidr-27-luaxform-equivalent + +Demonstrates that a CIDR-dataset `isset` match replaces the +luaxform-based IP->CIDR-string pattern used by +`tests/lua/lua-transform-09`, without per-packet Lua invocation. Two +rules mirror lua-transform-09's semantics: + +- sid:1 uses `ip.src` with `net-src.lst` containing `10.20.48.0/24` +- sid:2 uses `ip.dst` with `net-dst.lst` containing `10.50.0.0/16` + +Reuses `../../lua/lua-transform-01/test.pcap` (the same pcap that +lua-transform-09 loads via `../lua-transform-01/test.pcap`) and +asserts the same 4+4 alert counts. + +## Shared pcap relationships + +``` +input-ipv4.pcap (in datasets-cidr-01-ipv4-isset/) + used by: 01, 02, 03, 04, 08, 10, 16 + +input-ipv6.pcap (in datasets-cidr-05-ipv6-isset/) + used by: 05, 06 + +input-mixed.pcap (in datasets-cidr-07-mixed/) + used by: 07 only + +input-boundary.pcap (in datasets-cidr-09-boundary/) + used by: 09 only + +input.pcap (in datasets-cidr-11-set/) + used by: 11 only + +input.pcap (in datasets-cidr-12-unset/) + used by: 12 only + +input.pcap (in datasets-cidr-15-mask/) + used by: 15, 17, 18 + +input.pcap (in datasets-cidr-19-unset-mask/) + used by: 19 only + +input-ipv6.pcap (in datasets-cidr-20-ipv6-set/) + used by: 20 only + +input-ipv6.pcap (in datasets-cidr-21-ipv6-unset/) + used by: 21 only +``` + +Tests 13, 14, 22, 23, 24, 25, and 26 do not use a pcap; they are +rejection tests that exercise `--engine-analysis` and grep the log. + +Test 27 reuses `../../lua/lua-transform-01/test.pcap` from a +different test group to mirror the assertions of +`tests/lua/lua-transform-09`. diff --git a/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/input-ipv4.pcap b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/input-ipv4.pcap new file mode 100644 index 0000000000..f419672bf9 Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/input-ipv4.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/rfc1918.lst b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/rfc1918.lst new file mode 100644 index 0000000000..bc4609bb9b --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/rfc1918.lst @@ -0,0 +1,3 @@ +192.168.0.0/16 +10.0.0.0/8 +172.16.0.0/12 diff --git a/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/test.rules b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/test.rules new file mode 100644 index 0000000000..3cce559da7 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"RFC1918 src"; ip.src; dataset:isset,rfc1918,type cidr,load rfc1918.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/test.yaml b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/test.yaml new file mode 100644 index 0000000000..1f4fcd58f5 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/test.yaml @@ -0,0 +1,46 @@ +requires: + min-version: 9 + +pcap: input-ipv4.pcap + +args: + - -k none + +checks: + - filter: + count: 3 + match: + event_type: alert + - filter: + count: 3 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.1.5" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "10.0.0.50" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "172.17.0.1" + - filter: + count: 0 + match: + event_type: alert + src_ip: "1.2.3.4" + - filter: + count: 0 + match: + event_type: alert + src_ip: "203.0.113.1" diff --git a/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/writepcap.py b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/writepcap.py new file mode 100644 index 0000000000..9fb0fa3c27 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-01-ipv4-isset/writepcap.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IP, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# 192.168.1.5 - in RFC1918 (192.168.0.0/16) - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.1.5', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +# 10.0.0.50 - in RFC1918 (10.0.0.0/8) - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='10.0.0.50', dst='8.8.8.8') / + UDP(sport=1235, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 172.17.0.1 - in RFC1918 (172.16.0.0/12) - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='172.17.0.1', dst='8.8.8.8') / + UDP(sport=1236, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +# 1.2.3.4 - public IP - should NOT match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='1.2.3.4', dst='8.8.8.8') / + UDP(sport=1237, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +# 203.0.113.1 - public IP (TEST-NET-3) - should NOT match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='203.0.113.1', dst='8.8.8.8') / + UDP(sport=1238, dport=53) / + DNS(id=5, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input-ipv4.pcap', pkts) +print("Wrote input-ipv4.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/rfc1918.lst b/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/rfc1918.lst new file mode 100644 index 0000000000..bc4609bb9b --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/rfc1918.lst @@ -0,0 +1,3 @@ +192.168.0.0/16 +10.0.0.0/8 +172.16.0.0/12 diff --git a/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/test.rules b/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/test.rules new file mode 100644 index 0000000000..c590df4c86 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"Not RFC1918 src"; ip.src; dataset:isnotset,rfc1918,type cidr,load rfc1918.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/test.yaml b/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/test.yaml new file mode 100644 index 0000000000..3ddbe822d4 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-02-ipv4-isnotset/test.yaml @@ -0,0 +1,45 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-01-ipv4-isset/input-ipv4.pcap + +args: + - -k none + +checks: + - filter: + count: 2 + match: + event_type: alert + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "1.2.3.4" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "203.0.113.1" + - filter: + count: 0 + match: + event_type: alert + src_ip: "192.168.1.5" + - filter: + count: 0 + match: + event_type: alert + src_ip: "10.0.0.50" + - filter: + count: 0 + match: + event_type: alert + src_ip: "172.17.0.1" diff --git a/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/google-dns.lst b/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/google-dns.lst new file mode 100644 index 0000000000..d4c44f5c23 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/google-dns.lst @@ -0,0 +1 @@ +8.8.0.0/16 diff --git a/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/test.rules b/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/test.rules new file mode 100644 index 0000000000..c3c5d3e8be --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"Google DNS dst"; ip.dst; dataset:isset,google-dns,type cidr,load google-dns.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/test.yaml b/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/test.yaml new file mode 100644 index 0000000000..d3aa3eb3f7 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-03-ipv4-dst/test.yaml @@ -0,0 +1,24 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-01-ipv4-isset/input-ipv4.pcap + +args: + - -k none + +checks: + - filter: + count: 5 + match: + event_type: alert + - filter: + count: 5 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 5 + match: + event_type: alert + alert.signature_id: 1 + dest_ip: "8.8.8.8" diff --git a/tests/datasets-cidr/datasets-cidr-04-multi-rule/rfc1918.lst b/tests/datasets-cidr/datasets-cidr-04-multi-rule/rfc1918.lst new file mode 100644 index 0000000000..bc4609bb9b --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-04-multi-rule/rfc1918.lst @@ -0,0 +1,3 @@ +192.168.0.0/16 +10.0.0.0/8 +172.16.0.0/12 diff --git a/tests/datasets-cidr/datasets-cidr-04-multi-rule/test.rules b/tests/datasets-cidr/datasets-cidr-04-multi-rule/test.rules new file mode 100644 index 0000000000..008612cd0d --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-04-multi-rule/test.rules @@ -0,0 +1,2 @@ +alert ip any any -> any any (msg:"RFC1918 src isset"; ip.src; dataset:isset,rfc1918,type cidr,load rfc1918.lst; sid:1;) +alert ip any any -> any any (msg:"RFC1918 dst isnotset"; ip.dst; dataset:isnotset,rfc1918,type cidr,load rfc1918.lst; sid:2;) diff --git a/tests/datasets-cidr/datasets-cidr-04-multi-rule/test.yaml b/tests/datasets-cidr/datasets-cidr-04-multi-rule/test.yaml new file mode 100644 index 0000000000..b362496e4a --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-04-multi-rule/test.yaml @@ -0,0 +1,47 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-01-ipv4-isset/input-ipv4.pcap + +args: + - -k none + +checks: + - filter: + count: 8 + match: + event_type: alert + - filter: + count: 3 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.1.5" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "10.0.0.50" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "172.17.0.1" + - filter: + count: 5 + match: + event_type: alert + alert.signature_id: 2 + - filter: + count: 5 + match: + event_type: alert + alert.signature_id: 2 + dest_ip: "8.8.8.8" diff --git a/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/input-ipv6.pcap b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/input-ipv6.pcap new file mode 100644 index 0000000000..c57d3b2d70 Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/input-ipv6.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/suricata.yaml b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/suricata.yaml new file mode 100644 index 0000000000..13886ea648 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/suricata.yaml @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +outputs: + - eve-log: + enabled: true + ipv6-compress: yes + types: + - alert diff --git a/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/test.rules b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/test.rules new file mode 100644 index 0000000000..e32523ace6 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"ULA src"; ip.src; dataset:isset,ula,type cidr,load ula.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/test.yaml b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/test.yaml new file mode 100644 index 0000000000..877393701a --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/test.yaml @@ -0,0 +1,40 @@ +requires: + min-version: 9 + +pcap: input-ipv6.pcap + +args: + - -k none + +checks: + - filter: + count: 2 + match: + event_type: alert + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "fc00::1" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "fd12:3456::1" + - filter: + count: 0 + match: + event_type: alert + src_ip: "2001:db8::1" + - filter: + count: 0 + match: + event_type: alert + src_ip: "fe80::1" diff --git a/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/ula.lst b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/ula.lst new file mode 100644 index 0000000000..fecb0d3dce --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/ula.lst @@ -0,0 +1 @@ +fc00::/7 diff --git a/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/writepcap.py b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/writepcap.py new file mode 100644 index 0000000000..3fc8d29e1f --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-05-ipv6-isset/writepcap.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IPv6, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# fc00::1 - in ULA range (fc00::/7) - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fc00::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +# fd12:3456::1 - in ULA range (fc00::/7 covers fd::/8 too) - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fd12:3456::1', dst='2001:db8::53') / + UDP(sport=1235, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 2001:db8::1 - documentation prefix, not ULA - should NOT match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='2001:db8::1', dst='2001:db8::53') / + UDP(sport=1236, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +# fe80::1 - link-local, not ULA - should NOT match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fe80::1', dst='2001:db8::53') / + UDP(sport=1237, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input-ipv6.pcap', pkts) +print("Wrote input-ipv6.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/suricata.yaml b/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/suricata.yaml new file mode 100644 index 0000000000..13886ea648 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/suricata.yaml @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +outputs: + - eve-log: + enabled: true + ipv6-compress: yes + types: + - alert diff --git a/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/test.rules b/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/test.rules new file mode 100644 index 0000000000..d10b07de6b --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"Not ULA src"; ip.src; dataset:isnotset,ula,type cidr,load ula.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/test.yaml b/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/test.yaml new file mode 100644 index 0000000000..9f904ee236 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/test.yaml @@ -0,0 +1,40 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-05-ipv6-isset/input-ipv6.pcap + +args: + - -k none + +checks: + - filter: + count: 2 + match: + event_type: alert + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "2001:db8::1" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "fe80::1" + - filter: + count: 0 + match: + event_type: alert + src_ip: "fc00::1" + - filter: + count: 0 + match: + event_type: alert + src_ip: "fd12:3456::1" diff --git a/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/ula.lst b/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/ula.lst new file mode 100644 index 0000000000..fecb0d3dce --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-06-ipv6-isnotset/ula.lst @@ -0,0 +1 @@ +fc00::/7 diff --git a/tests/datasets-cidr/datasets-cidr-07-mixed/input-mixed.pcap b/tests/datasets-cidr/datasets-cidr-07-mixed/input-mixed.pcap new file mode 100644 index 0000000000..d1d50eb90f Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-07-mixed/input-mixed.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-07-mixed/mixed.lst b/tests/datasets-cidr/datasets-cidr-07-mixed/mixed.lst new file mode 100644 index 0000000000..4b463a8d38 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-07-mixed/mixed.lst @@ -0,0 +1,2 @@ +192.168.0.0/16 +fc00::/7 diff --git a/tests/datasets-cidr/datasets-cidr-07-mixed/suricata.yaml b/tests/datasets-cidr/datasets-cidr-07-mixed/suricata.yaml new file mode 100644 index 0000000000..13886ea648 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-07-mixed/suricata.yaml @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +outputs: + - eve-log: + enabled: true + ipv6-compress: yes + types: + - alert diff --git a/tests/datasets-cidr/datasets-cidr-07-mixed/test.rules b/tests/datasets-cidr/datasets-cidr-07-mixed/test.rules new file mode 100644 index 0000000000..d607fa38f0 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-07-mixed/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"Mixed CIDR src"; ip.src; dataset:isset,mixed,type cidr,load mixed.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-07-mixed/test.yaml b/tests/datasets-cidr/datasets-cidr-07-mixed/test.yaml new file mode 100644 index 0000000000..d280442298 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-07-mixed/test.yaml @@ -0,0 +1,35 @@ +requires: + min-version: 9 + +pcap: input-mixed.pcap + +args: + - -k none + +checks: + - filter: + count: 2 + match: + event_type: alert + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.1.5" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "fc00::1" + - filter: + count: 0 + match: + event_type: alert + src_ip: "1.2.3.4" diff --git a/tests/datasets-cidr/datasets-cidr-07-mixed/writepcap.py b/tests/datasets-cidr/datasets-cidr-07-mixed/writepcap.py new file mode 100644 index 0000000000..9b970dc9db --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-07-mixed/writepcap.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IP, IPv6, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# IPv4: 192.168.1.5 - in 192.168.0.0/16 - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.1.5', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +# IPv6: fc00::1 - in fc00::/7 - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fc00::1', dst='2001:db8::1') / + UDP(sport=1235, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# IPv4: 1.2.3.4 - public IP, not in any CIDR - should NOT match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='1.2.3.4', dst='8.8.8.8') / + UDP(sport=1236, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input-mixed.pcap', pkts) +print("Wrote input-mixed.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-08-host-exact/host32.lst b/tests/datasets-cidr/datasets-cidr-08-host-exact/host32.lst new file mode 100644 index 0000000000..56addab521 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-08-host-exact/host32.lst @@ -0,0 +1 @@ +192.168.1.5/32 diff --git a/tests/datasets-cidr/datasets-cidr-08-host-exact/test.rules b/tests/datasets-cidr/datasets-cidr-08-host-exact/test.rules new file mode 100644 index 0000000000..9fad40fcfb --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-08-host-exact/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"Exact host /32"; ip.src; dataset:isset,host32,type cidr,load host32.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-08-host-exact/test.yaml b/tests/datasets-cidr/datasets-cidr-08-host-exact/test.yaml new file mode 100644 index 0000000000..73578774a9 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-08-host-exact/test.yaml @@ -0,0 +1,34 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-01-ipv4-isset/input-ipv4.pcap + +args: + - -k none + +checks: + - filter: + count: 1 + match: + event_type: alert + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.1.5" + - filter: + count: 0 + match: + event_type: alert + src_ip: "10.0.0.50" + - filter: + count: 0 + match: + event_type: alert + src_ip: "172.17.0.1" diff --git a/tests/datasets-cidr/datasets-cidr-09-boundary/boundary.lst b/tests/datasets-cidr/datasets-cidr-09-boundary/boundary.lst new file mode 100644 index 0000000000..e2c6a23343 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-09-boundary/boundary.lst @@ -0,0 +1 @@ +192.168.0.0/16 diff --git a/tests/datasets-cidr/datasets-cidr-09-boundary/input-boundary.pcap b/tests/datasets-cidr/datasets-cidr-09-boundary/input-boundary.pcap new file mode 100644 index 0000000000..40f34a9230 Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-09-boundary/input-boundary.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-09-boundary/test.rules b/tests/datasets-cidr/datasets-cidr-09-boundary/test.rules new file mode 100644 index 0000000000..b36735af5f --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-09-boundary/test.rules @@ -0,0 +1,2 @@ +alert ip any any -> any any (msg:"Boundary isset"; ip.src; dataset:isset,boundary,type cidr,load boundary.lst; sid:1;) +alert ip any any -> any any (msg:"Boundary isnotset"; ip.src; dataset:isnotset,boundary,type cidr,load boundary.lst; sid:2;) diff --git a/tests/datasets-cidr/datasets-cidr-09-boundary/test.yaml b/tests/datasets-cidr/datasets-cidr-09-boundary/test.yaml new file mode 100644 index 0000000000..741e477da9 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-09-boundary/test.yaml @@ -0,0 +1,47 @@ +requires: + min-version: 9 + +pcap: input-boundary.pcap + +args: + - -k none + +checks: + - filter: + count: 4 + match: + event_type: alert + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.0.0" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.255.255" + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 2 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 2 + src_ip: "192.169.0.1" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 2 + src_ip: "192.167.255.255" diff --git a/tests/datasets-cidr/datasets-cidr-09-boundary/writepcap.py b/tests/datasets-cidr/datasets-cidr-09-boundary/writepcap.py new file mode 100644 index 0000000000..58aca62f51 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-09-boundary/writepcap.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IP, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# 192.168.0.0 - first address of 192.168.0.0/16 - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.0.0', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +# 192.168.255.255 - last address of 192.168.0.0/16 - should match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.255.255', dst='8.8.8.8') / + UDP(sport=1235, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 192.169.0.1 - one above 192.168.0.0/16 - should NOT match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.169.0.1', dst='8.8.8.8') / + UDP(sport=1236, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +# 192.167.255.255 - one below 192.168.0.0/16 - should NOT match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.167.255.255', dst='8.8.8.8') / + UDP(sport=1237, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input-boundary.pcap', pkts) +print("Wrote input-boundary.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-10-empty/empty.lst b/tests/datasets-cidr/datasets-cidr-10-empty/empty.lst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/datasets-cidr/datasets-cidr-10-empty/test.rules b/tests/datasets-cidr/datasets-cidr-10-empty/test.rules new file mode 100644 index 0000000000..0c256c1b40 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-10-empty/test.rules @@ -0,0 +1,2 @@ +alert ip any any -> any any (msg:"Empty CIDR isset"; ip.src; dataset:isset,empty-cidr,type cidr,load empty.lst; sid:1;) +alert ip any any -> any any (msg:"Empty CIDR isnotset"; ip.src; dataset:isnotset,empty-cidr,type cidr,load empty.lst; sid:2;) diff --git a/tests/datasets-cidr/datasets-cidr-10-empty/test.yaml b/tests/datasets-cidr/datasets-cidr-10-empty/test.yaml new file mode 100644 index 0000000000..dd0a6c1d30 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-10-empty/test.yaml @@ -0,0 +1,53 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-01-ipv4-isset/input-ipv4.pcap + +args: + - -k none + +checks: + - filter: + count: 5 + match: + event_type: alert + - filter: + count: 0 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 5 + match: + event_type: alert + alert.signature_id: 2 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 2 + src_ip: "192.168.1.5" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 2 + src_ip: "10.0.0.50" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 2 + src_ip: "172.17.0.1" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 2 + src_ip: "1.2.3.4" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 2 + src_ip: "203.0.113.1" diff --git a/tests/datasets-cidr/datasets-cidr-11-set/input.pcap b/tests/datasets-cidr/datasets-cidr-11-set/input.pcap new file mode 100644 index 0000000000..21e538ad15 Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-11-set/input.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-11-set/test.rules b/tests/datasets-cidr/datasets-cidr-11-set/test.rules new file mode 100644 index 0000000000..794823bca4 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-11-set/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR set new host"; ip.src; dataset:set,dynamic-cidr,type cidr; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-11-set/test.yaml b/tests/datasets-cidr/datasets-cidr-11-set/test.yaml new file mode 100644 index 0000000000..48b699a098 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-11-set/test.yaml @@ -0,0 +1,27 @@ +requires: + min-version: 9 + +pcap: input.pcap + +args: + - -k none + +checks: + # set fires only once per unique source address (new entry only) + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "1.2.3.4" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "5.6.7.8" diff --git a/tests/datasets-cidr/datasets-cidr-11-set/writepcap.py b/tests/datasets-cidr/datasets-cidr-11-set/writepcap.py new file mode 100644 index 0000000000..40bdf97bfe --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-11-set/writepcap.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IP, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# 2 packets from 1.2.3.4 - first fires 'set' (new), second does not +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='1.2.3.4', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='1.2.3.4', dst='8.8.8.8') / + UDP(sport=1235, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 2 packets from 5.6.7.8 - first fires 'set' (new), second does not +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='5.6.7.8', dst='8.8.8.8') / + UDP(sport=1236, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='5.6.7.8', dst='8.8.8.8') / + UDP(sport=1237, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input.pcap', pkts) +print("Wrote input.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-12-unset/host.lst b/tests/datasets-cidr/datasets-cidr-12-unset/host.lst new file mode 100644 index 0000000000..4065cb7caa --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-12-unset/host.lst @@ -0,0 +1,2 @@ +1.2.3.4 +5.6.7.8 diff --git a/tests/datasets-cidr/datasets-cidr-12-unset/input.pcap b/tests/datasets-cidr/datasets-cidr-12-unset/input.pcap new file mode 100644 index 0000000000..83ad8991f4 Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-12-unset/input.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-12-unset/test.rules b/tests/datasets-cidr/datasets-cidr-12-unset/test.rules new file mode 100644 index 0000000000..58d9696cfc --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-12-unset/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR unset host"; ip.src; dataset:unset,host-unset,type cidr,load host.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-12-unset/test.yaml b/tests/datasets-cidr/datasets-cidr-12-unset/test.yaml new file mode 100644 index 0000000000..5d43335c24 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-12-unset/test.yaml @@ -0,0 +1,33 @@ +requires: + min-version: 9 + +pcap: input.pcap + +args: + - -k none + +checks: + # unset fires once per pre-loaded host address (removes it on first match) + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "1.2.3.4" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "5.6.7.8" + # 9.9.9.9 was never in the set, unset does not fire + - filter: + count: 0 + match: + event_type: alert + src_ip: "9.9.9.9" diff --git a/tests/datasets-cidr/datasets-cidr-12-unset/writepcap.py b/tests/datasets-cidr/datasets-cidr-12-unset/writepcap.py new file mode 100644 index 0000000000..e01ef169c8 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-12-unset/writepcap.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IP, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# 2 packets from 1.2.3.4 (pre-loaded as /32) - first unsets it, second does not match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='1.2.3.4', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='1.2.3.4', dst='8.8.8.8') / + UDP(sport=1235, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 2 packets from 5.6.7.8 (pre-loaded as /32) - first unsets it, second does not match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='5.6.7.8', dst='8.8.8.8') / + UDP(sport=1236, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='5.6.7.8', dst='8.8.8.8') / + UDP(sport=1237, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +# 1 packet from 9.9.9.9 (never in set) - does not match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='9.9.9.9', dst='8.8.8.8') / + UDP(sport=1238, dport=53) / + DNS(id=5, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input.pcap', pkts) +print("Wrote input.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-13-save-reject/test.rules b/tests/datasets-cidr/datasets-cidr-13-save-reject/test.rules new file mode 100644 index 0000000000..2ccbf1ec98 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-13-save-reject/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR with save"; ip.src; dataset:isset,my-cidr,type cidr,save out.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-13-save-reject/test.yaml b/tests/datasets-cidr/datasets-cidr-13-save-reject/test.yaml new file mode 100644 index 0000000000..a17f68518e --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-13-save-reject/test.yaml @@ -0,0 +1,13 @@ +requires: + min-version: 9 + pcap: false + +exit-code: 1 + +args: + - --engine-analysis + +checks: + - shell: + args: grep "save/state is not supported for CIDR datasets" suricata.log | wc -l | xargs + expect: 1 diff --git a/tests/datasets-cidr/datasets-cidr-14-state-reject/test.rules b/tests/datasets-cidr/datasets-cidr-14-state-reject/test.rules new file mode 100644 index 0000000000..27c47ef07c --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-14-state-reject/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR with state"; ip.src; dataset:isset,my-cidr,type cidr,state cidr.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-14-state-reject/test.yaml b/tests/datasets-cidr/datasets-cidr-14-state-reject/test.yaml new file mode 100644 index 0000000000..a17f68518e --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-14-state-reject/test.yaml @@ -0,0 +1,13 @@ +requires: + min-version: 9 + pcap: false + +exit-code: 1 + +args: + - --engine-analysis + +checks: + - shell: + args: grep "save/state is not supported for CIDR datasets" suricata.log | wc -l | xargs + expect: 1 diff --git a/tests/datasets-cidr/datasets-cidr-15-mask/input.pcap b/tests/datasets-cidr/datasets-cidr-15-mask/input.pcap new file mode 100644 index 0000000000..ba1f334374 Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-15-mask/input.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-15-mask/test.rules b/tests/datasets-cidr/datasets-cidr-15-mask/test.rules new file mode 100644 index 0000000000..0a9c7595de --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-15-mask/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR set with mask 24"; ip.src; dataset:set,masked-cidr,type cidr,mask 24; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-15-mask/test.yaml b/tests/datasets-cidr/datasets-cidr-15-mask/test.yaml new file mode 100644 index 0000000000..6209ff16d5 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-15-mask/test.yaml @@ -0,0 +1,29 @@ +requires: + min-version: 9 + +pcap: input.pcap + +args: + - -k none + +checks: + # set+mask 24 fires once per unique /24 prefix; 2 packets per /24 → 2 alerts total + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + # first packet from 192.168.1.5 adds 192.168.1.0/24 (fires) + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.1.5" + # first packet from 192.168.2.1 adds 192.168.2.0/24 (fires) + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.2.1" diff --git a/tests/datasets-cidr/datasets-cidr-15-mask/writepcap.py b/tests/datasets-cidr/datasets-cidr-15-mask/writepcap.py new file mode 100644 index 0000000000..ded3ad7fd6 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-15-mask/writepcap.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IP, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# 2 packets from 192.168.1.5 using the same 5-tuple (same flow, same worker). +# First masks to 192.168.1.0/24 and adds it (new -> fires); second finds it +# already present (no fire). +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.1.5', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.1.5', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 2 packets from 192.168.2.1 using the same 5-tuple (same flow, same worker). +# First adds 192.168.2.0/24 (new -> fires); second finds it already present. +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.2.1', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.2.1', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input.pcap', pkts) +print("Wrote input.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-16-lua/.cidr-check.lua.swp b/tests/datasets-cidr/datasets-cidr-16-lua/.cidr-check.lua.swp new file mode 100644 index 0000000000..8c4409aa36 Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-16-lua/.cidr-check.lua.swp differ diff --git a/tests/datasets-cidr/datasets-cidr-16-lua/cidr-check.lua b/tests/datasets-cidr/datasets-cidr-16-lua/cidr-check.lua new file mode 100644 index 0000000000..95b627b496 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-16-lua/cidr-check.lua @@ -0,0 +1,29 @@ +local dataset = require "suricata.dataset" +local logger = require "suricata.log" + +local dataset_ok = false + +function init(args) + local needs = {} + needs["packet"] = tostring(true) + return needs +end + +function thread_init(args) + local ds_obj = dataset.new() + local ret, err = ds_obj:get("rfc1918-cidr") + if err ~= nil then + logger.warning("CIDR dataset get failed: " .. err) + dataset_ok = false + return 0 + end + dataset_ok = true +end + +-- Return 1 only when the CIDR dataset was successfully retrieved via get() +function match(args) + if not dataset_ok then + return 0 + end + return 1 +end diff --git a/tests/datasets-cidr/datasets-cidr-16-lua/cidr.lst b/tests/datasets-cidr/datasets-cidr-16-lua/cidr.lst new file mode 100644 index 0000000000..b14f30408b --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-16-lua/cidr.lst @@ -0,0 +1,3 @@ +10.0.0.0/8 +192.168.0.0/16 +172.16.0.0/12 diff --git a/tests/datasets-cidr/datasets-cidr-16-lua/test.rules b/tests/datasets-cidr/datasets-cidr-16-lua/test.rules new file mode 100644 index 0000000000..29d2938990 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-16-lua/test.rules @@ -0,0 +1,2 @@ +alert ip any any -> any any (msg:"RFC1918 CIDR isset"; ip.src; dataset:isset,rfc1918-cidr,type cidr,load cidr.lst; sid:1;) +alert ip any any -> any any (msg:"Lua CIDR dataset access"; lua:cidr-check.lua; sid:2;) diff --git a/tests/datasets-cidr/datasets-cidr-16-lua/test.yaml b/tests/datasets-cidr/datasets-cidr-16-lua/test.yaml new file mode 100644 index 0000000000..1fef596411 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-16-lua/test.yaml @@ -0,0 +1,26 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-01-ipv4-isset/input-ipv4.pcap + +args: + - -k none + - --set default-rule-path=. + +checks: + # sid:1 (isset) fires for RFC1918 sources: 192.168.1.5, 10.0.0.50, 172.17.0.1 + - filter: + count: 3 + match: + event_type: alert + alert.signature_id: 1 + # sid:2 (lua) fires for every packet when Lua can access the CIDR dataset + - filter: + count: 5 + match: + event_type: alert + alert.signature_id: 2 + # no warning about "CIDR dataset get failed" in the log + - shell: + args: grep "CIDR dataset get failed" suricata.log | wc -l | xargs + expect: 0 diff --git a/tests/datasets-cidr/datasets-cidr-17-mask-hex-prefix/test.rules b/tests/datasets-cidr/datasets-cidr-17-mask-hex-prefix/test.rules new file mode 100644 index 0000000000..265513698a --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-17-mask-hex-prefix/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR set with mask 0x18 (hex prefix == /24)"; ip.src; dataset:set,masked-cidr,type cidr,mask 0x18; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-17-mask-hex-prefix/test.yaml b/tests/datasets-cidr/datasets-cidr-17-mask-hex-prefix/test.yaml new file mode 100644 index 0000000000..81113a8fa4 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-17-mask-hex-prefix/test.yaml @@ -0,0 +1,27 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-15-mask/input.pcap + +args: + - -k none + +checks: + # mask 0x18 is hex for /24; behavior identical to mask 24 + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.1.5" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.2.1" diff --git a/tests/datasets-cidr/datasets-cidr-18-mask-bitmask/test.rules b/tests/datasets-cidr/datasets-cidr-18-mask-bitmask/test.rules new file mode 100644 index 0000000000..54844e5ebb --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-18-mask-bitmask/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR set with mask 0xffffff00 (bitmask == /24)"; ip.src; dataset:set,masked-cidr,type cidr,mask 0xffffff00; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-18-mask-bitmask/test.yaml b/tests/datasets-cidr/datasets-cidr-18-mask-bitmask/test.yaml new file mode 100644 index 0000000000..687c9b58fc --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-18-mask-bitmask/test.yaml @@ -0,0 +1,27 @@ +requires: + min-version: 9 + +pcap: ../datasets-cidr-15-mask/input.pcap + +args: + - -k none + +checks: + # mask 0xffffff00 is the IPv4 bitmask for /24; behavior identical to mask 24 + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.1.5" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.2.1" diff --git a/tests/datasets-cidr/datasets-cidr-19-unset-mask/cidr.lst b/tests/datasets-cidr/datasets-cidr-19-unset-mask/cidr.lst new file mode 100644 index 0000000000..87ef5264d8 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-19-unset-mask/cidr.lst @@ -0,0 +1,2 @@ +192.168.1.0/24 +192.168.2.0/24 diff --git a/tests/datasets-cidr/datasets-cidr-19-unset-mask/input.pcap b/tests/datasets-cidr/datasets-cidr-19-unset-mask/input.pcap new file mode 100644 index 0000000000..324b4cb2d0 Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-19-unset-mask/input.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-19-unset-mask/test.rules b/tests/datasets-cidr/datasets-cidr-19-unset-mask/test.rules new file mode 100644 index 0000000000..f07e89cf8c --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-19-unset-mask/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR unset with mask 24"; ip.src; dataset:unset,prefix-unset,type cidr,load cidr.lst,mask 24; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-19-unset-mask/test.yaml b/tests/datasets-cidr/datasets-cidr-19-unset-mask/test.yaml new file mode 100644 index 0000000000..f63cb6b731 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-19-unset-mask/test.yaml @@ -0,0 +1,35 @@ +requires: + min-version: 9 + +pcap: input.pcap + +args: + - -k none + +checks: + # unset,mask 24 fires once per /24 loaded from file (removes it on first match) + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + # first packet from 192.168.1.5 masks to 192.168.1.0/24 and removes it + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.1.5" + # second packet from 192.168.1.5: /24 already removed, does not fire + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "192.168.2.1" + # 10.0.0.0/24 was not in the dataset, never fires + - filter: + count: 0 + match: + event_type: alert + src_ip: "10.0.0.1" diff --git a/tests/datasets-cidr/datasets-cidr-19-unset-mask/writepcap.py b/tests/datasets-cidr/datasets-cidr-19-unset-mask/writepcap.py new file mode 100644 index 0000000000..e9897bf1d9 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-19-unset-mask/writepcap.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IP, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# 2 packets from 192.168.1.5 (in 192.168.1.0/24) +# unset,mask 24: first masks to /24 and removes it (fires), second finds /24 gone (no fire) +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.1.5', dst='8.8.8.8') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.1.5', dst='8.8.8.8') / + UDP(sport=1235, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 2 packets from 192.168.2.1 (in 192.168.2.0/24) +# unset,mask 24: first removes /24 (fires), second finds /24 gone (no fire) +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.2.1', dst='8.8.8.8') / + UDP(sport=1236, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='192.168.2.1', dst='8.8.8.8') / + UDP(sport=1237, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +# 1 packet from 10.0.0.1: masked to 10.0.0.0/24, not in dataset, no fire +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IP(src='10.0.0.1', dst='8.8.8.8') / + UDP(sport=1238, dport=53) / + DNS(id=5, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input.pcap', pkts) +print("Wrote input.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-20-ipv6-set/input-ipv6.pcap b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/input-ipv6.pcap new file mode 100644 index 0000000000..d1aded9dce Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/input-ipv6.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-20-ipv6-set/suricata.yaml b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/suricata.yaml new file mode 100644 index 0000000000..13886ea648 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/suricata.yaml @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +outputs: + - eve-log: + enabled: true + ipv6-compress: yes + types: + - alert diff --git a/tests/datasets-cidr/datasets-cidr-20-ipv6-set/test.rules b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/test.rules new file mode 100644 index 0000000000..82435d270e --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"IPv6 CIDR set new host"; ip.src; dataset:set,ipv6-dynamic,type cidr; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-20-ipv6-set/test.yaml b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/test.yaml new file mode 100644 index 0000000000..410ec923c4 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/test.yaml @@ -0,0 +1,27 @@ +requires: + min-version: 9 + +pcap: input-ipv6.pcap + +args: + - -k none + +checks: + # set fires only once per unique IPv6 source address (new entry only) + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "fc00::1" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "2001:db8::1" diff --git a/tests/datasets-cidr/datasets-cidr-20-ipv6-set/writepcap.py b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/writepcap.py new file mode 100644 index 0000000000..a43824c8dc --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-20-ipv6-set/writepcap.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IPv6, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# 2 packets from fc00::1 - first fires 'set' (new), second does not +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fc00::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fc00::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 2 packets from 2001:db8::1 - first fires 'set' (new), second does not +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='2001:db8::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='2001:db8::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input-ipv6.pcap', pkts) +print("Wrote input-ipv6.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/host.lst b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/host.lst new file mode 100644 index 0000000000..3727c46a32 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/host.lst @@ -0,0 +1,2 @@ +fc00::1 +2001:db8::1 diff --git a/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/input-ipv6.pcap b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/input-ipv6.pcap new file mode 100644 index 0000000000..64ad341ded Binary files /dev/null and b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/input-ipv6.pcap differ diff --git a/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/suricata.yaml b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/suricata.yaml new file mode 100644 index 0000000000..13886ea648 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/suricata.yaml @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +outputs: + - eve-log: + enabled: true + ipv6-compress: yes + types: + - alert diff --git a/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/test.rules b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/test.rules new file mode 100644 index 0000000000..4d93376e44 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"IPv6 CIDR unset host"; ip.src; dataset:unset,ipv6-host-unset,type cidr,load host.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/test.yaml b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/test.yaml new file mode 100644 index 0000000000..1b9203bb74 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/test.yaml @@ -0,0 +1,33 @@ +requires: + min-version: 9 + +pcap: input-ipv6.pcap + +args: + - -k none + +checks: + # unset fires once per pre-loaded IPv6 address (removes it on first match) + - filter: + count: 2 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "fc00::1" + - filter: + count: 1 + match: + event_type: alert + alert.signature_id: 1 + src_ip: "2001:db8::1" + # fe80::1 was never in the set, unset does not fire + - filter: + count: 0 + match: + event_type: alert + src_ip: "fe80::1" diff --git a/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/writepcap.py b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/writepcap.py new file mode 100644 index 0000000000..59cb3f5eb5 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-21-ipv6-unset/writepcap.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +from scapy.all import Ether, IPv6, UDP, DNS, DNSQR, wrpcap + +pkts = [] + +# 2 packets from fc00::1 (pre-loaded as /128) - first unsets it, second no longer matches +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fc00::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=1, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fc00::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=2, rd=1, qd=DNSQR(qname='example.com'))) + +# 2 packets from 2001:db8::1 (pre-loaded as /128) - first unsets it, second no longer matches +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='2001:db8::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=3, rd=1, qd=DNSQR(qname='example.com'))) + +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='2001:db8::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=4, rd=1, qd=DNSQR(qname='example.com'))) + +# 1 packet from fe80::1 (never in set) - does not match +pkts.append(Ether(dst='ff:ff:ff:ff:ff:ff', src='00:01:02:03:04:05') / + IPv6(src='fe80::1', dst='2001:db8::53') / + UDP(sport=1234, dport=53) / + DNS(id=5, rd=1, qd=DNSQR(qname='example.com'))) + +wrpcap('input-ipv6.pcap', pkts) +print("Wrote input-ipv6.pcap with %d packets" % len(pkts)) diff --git a/tests/datasets-cidr/datasets-cidr-22-mask-isset-reject/test.rules b/tests/datasets-cidr/datasets-cidr-22-mask-isset-reject/test.rules new file mode 100644 index 0000000000..b2a450d9f9 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-22-mask-isset-reject/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR isset with mask"; ip.src; dataset:isset,my-cidr,type cidr,mask 24; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-22-mask-isset-reject/test.yaml b/tests/datasets-cidr/datasets-cidr-22-mask-isset-reject/test.yaml new file mode 100644 index 0000000000..75bed4138e --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-22-mask-isset-reject/test.yaml @@ -0,0 +1,13 @@ +requires: + min-version: 9 + pcap: false + +exit-code: 1 + +args: + - --engine-analysis + +checks: + - shell: + args: grep "mask is only supported for CIDR datasets with 'set' and 'unset' commands" suricata.log | wc -l | xargs + expect: 1 diff --git a/tests/datasets-cidr/datasets-cidr-23-mask-out-of-range/test.rules b/tests/datasets-cidr/datasets-cidr-23-mask-out-of-range/test.rules new file mode 100644 index 0000000000..08cac9b6e2 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-23-mask-out-of-range/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR set with non-contiguous bitmask"; ip.src; dataset:set,my-cidr,type cidr,mask 0x00ff00ff; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-23-mask-out-of-range/test.yaml b/tests/datasets-cidr/datasets-cidr-23-mask-out-of-range/test.yaml new file mode 100644 index 0000000000..2d6cf5fc00 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-23-mask-out-of-range/test.yaml @@ -0,0 +1,13 @@ +requires: + min-version: 9 + pcap: false + +exit-code: 1 + +args: + - --engine-analysis + +checks: + - shell: + args: grep "not a contiguous IPv4 netmask" suricata.log | wc -l | xargs + expect: 1 diff --git a/tests/datasets-cidr/datasets-cidr-24-mask-non-cidr-reject/test.rules b/tests/datasets-cidr/datasets-cidr-24-mask-non-cidr-reject/test.rules new file mode 100644 index 0000000000..d027502038 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-24-mask-non-cidr-reject/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"mask with non-CIDR type"; ip.src; dataset:set,my-ipv4,type ipv4,mask 24; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-24-mask-non-cidr-reject/test.yaml b/tests/datasets-cidr/datasets-cidr-24-mask-non-cidr-reject/test.yaml new file mode 100644 index 0000000000..695a427405 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-24-mask-non-cidr-reject/test.yaml @@ -0,0 +1,13 @@ +requires: + min-version: 9 + pcap: false + +exit-code: 1 + +args: + - --engine-analysis + +checks: + - shell: + args: grep "mask is only supported for CIDR datasets" suricata.log | wc -l | xargs + expect: 1 diff --git a/tests/datasets-cidr/datasets-cidr-25-datarep-cidr-reject/test.rules b/tests/datasets-cidr/datasets-cidr-25-datarep-cidr-reject/test.rules new file mode 100644 index 0000000000..51abe9334c --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-25-datarep-cidr-reject/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"datarep with cidr type"; ip.src; datarep:my-rep,>,10,type cidr,load rep.lst; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-25-datarep-cidr-reject/test.yaml b/tests/datasets-cidr/datasets-cidr-25-datarep-cidr-reject/test.yaml new file mode 100644 index 0000000000..58c3100c45 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-25-datarep-cidr-reject/test.yaml @@ -0,0 +1,14 @@ +requires: + min-version: 9 + pcap: false + +exit-code: 1 + +args: + - --engine-analysis + +checks: + # datarep does not support type cidr; the sig fails to parse. + - shell: + args: grep 'error parsing signature' suricata.log | wc -l | xargs + expect: 1 diff --git a/tests/datasets-cidr/datasets-cidr-26-mask-zero-reject/test.rules b/tests/datasets-cidr/datasets-cidr-26-mask-zero-reject/test.rules new file mode 100644 index 0000000000..88741d18b5 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-26-mask-zero-reject/test.rules @@ -0,0 +1 @@ +alert ip any any -> any any (msg:"CIDR set with mask 0"; ip.src; dataset:set,my-cidr,type cidr,mask 0; sid:1;) diff --git a/tests/datasets-cidr/datasets-cidr-26-mask-zero-reject/test.yaml b/tests/datasets-cidr/datasets-cidr-26-mask-zero-reject/test.yaml new file mode 100644 index 0000000000..18e14ef88b --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-26-mask-zero-reject/test.yaml @@ -0,0 +1,13 @@ +requires: + min-version: 9 + pcap: false + +exit-code: 1 + +args: + - --engine-analysis + +checks: + - shell: + args: grep "prefix length 0 is not allowed" suricata.log | wc -l | xargs + expect: 1 diff --git a/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/net-dst.lst b/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/net-dst.lst new file mode 100644 index 0000000000..2ddc1d2060 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/net-dst.lst @@ -0,0 +1 @@ +10.50.0.0/16 diff --git a/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/net-src.lst b/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/net-src.lst new file mode 100644 index 0000000000..d79eae923e --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/net-src.lst @@ -0,0 +1 @@ +10.20.48.0/24 diff --git a/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/test.rules b/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/test.rules new file mode 100644 index 0000000000..f08517a713 --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/test.rules @@ -0,0 +1,2 @@ +alert http any any -> any any (msg:"src in 10.20.48.0/24"; flow:established; ip.src; dataset:isset,net-src,type cidr,load net-src.lst; sid:1;) +alert http any any -> any any (msg:"dst in 10.50.0.0/16"; flow:established; ip.dst; dataset:isset,net-dst,type cidr,load net-dst.lst; sid:2;) diff --git a/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/test.yaml b/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/test.yaml new file mode 100644 index 0000000000..6e5dceb34c --- /dev/null +++ b/tests/datasets-cidr/datasets-cidr-27-luaxform-equivalent/test.yaml @@ -0,0 +1,21 @@ +requires: + min-version: 9 + +# Reuses the same pcap as tests/lua/lua-transform-09 so the CIDR-dataset +# rules produce the same alert counts (4 for sid:1, 4 for sid:2) that the +# luaxform equivalents produce there. Demonstrates that a CIDR-dataset +# isset match replaces the luaxform IP->CIDR-string pattern without any +# per-packet Lua invocation. +pcap: ../../lua/lua-transform-01/test.pcap + +checks: + - filter: + count: 4 + match: + event_type: alert + alert.signature_id: 1 + - filter: + count: 4 + match: + event_type: alert + alert.signature_id: 2