Skip to content

Commit

Permalink
tests: add bug 7422 tests
Browse files Browse the repository at this point in the history
Tests various forms of RST triggering handling of unACK'd data.
  • Loading branch information
victorjulien committed Nov 30, 2024
1 parent 2f97c25 commit a582ae0
Show file tree
Hide file tree
Showing 40 changed files with 352 additions and 0 deletions.
8 changes: 8 additions & 0 deletions tests/tcp-rst-unacked-stream-01-raw/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Test
====

Test series that tests if a RST that comes in before all data is ACK'd the
unACK'd data is still reassembled and inspected, but does not trigger a GAP
event.

This test tests raw reassembly inspection of unack'd data w/o GAP.
Binary file added tests/tcp-rst-unacked-stream-01-raw/input.pcap
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/tcp-rst-unacked-stream-01-raw/test.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alert tcp any any -> any any (content:"Let Me In"; sid:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; threshold:type backoff, track by_flow, count 1, multiplier 10; classtype:protocol-command-decode; sid:2210048; rev:3;)
18 changes: 18 additions & 0 deletions tests/tcp-rst-unacked-stream-01-raw/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

checks:
- filter:
count: 1
match:
event_type: alert
alert.signature_id: 1
pkt_src: "stream (flow timeout)"
- filter:
count: 0
match:
event_type: alert
alert.signature_id: 2210048
- filter:
count: 1
match:
event_type: stats
stats.tcp.reassembly_gap: 0
15 changes: 15 additions & 0 deletions tests/tcp-rst-unacked-stream-01-raw/writepcap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python
from scapy.all import *

pkts = []

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='S',seq=1,options=[('WScale', 14)])
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='SA',seq=1000,ack=2,options=[('WScale', 14)],window=65535)
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1001,ack=2,window=65535)/"Please "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1008,ack=2,window=65535)/"Let "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1012,ack=2,window=65535)/"Me "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1015,ack=2,window=65535)/"In!"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='RA',seq=2,ack=1008,window=65535)/"Access Denied"

wrpcap('input.pcap', pkts)
8 changes: 8 additions & 0 deletions tests/tcp-rst-unacked-stream-02-raw-ips/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Test
====

Test series that tests if a RST that comes in before all data is ACK'd the
unACK'd data is still reassembled and inspected, but does not trigger a GAP
event.

This test tests raw reassembly inspection of unack'd data w/o GAP in IPS mode.
Binary file added tests/tcp-rst-unacked-stream-02-raw-ips/input.pcap
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/tcp-rst-unacked-stream-02-raw-ips/test.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alert tcp any any -> any any (content:"Let Me In"; sid:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; threshold:type backoff, track by_flow, count 1, multiplier 10; classtype:protocol-command-decode; sid:2210048; rev:3;)
18 changes: 18 additions & 0 deletions tests/tcp-rst-unacked-stream-02-raw-ips/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

checks:
- filter:
count: 1
match:
event_type: alert
alert.signature_id: 1
pcap_cnt: 7
- filter:
count: 0
match:
event_type: alert
alert.signature_id: 2210048
- filter:
count: 1
match:
event_type: stats
stats.tcp.reassembly_gap: 0
15 changes: 15 additions & 0 deletions tests/tcp-rst-unacked-stream-02-raw-ips/writepcap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python
from scapy.all import *

pkts = []

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='S',seq=1,options=[('WScale', 14)])
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='SA',seq=1000,ack=2,options=[('WScale', 14)],window=65535)
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1001,ack=2,window=65535)/"Please "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1008,ack=2,window=65535)/"Let "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1012,ack=2,window=65535)/"Me "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1015,ack=2,window=65535)/"In!"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='RA',seq=2,ack=1008,window=65535)/"Access Denied"

wrpcap('input.pcap', pkts)
8 changes: 8 additions & 0 deletions tests/tcp-rst-unacked-stream-03-gap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Test
====

Test series that tests if a RST that comes in before all data is ACK'd the
unACK'd data is still reassembled and inspected, but does not trigger a GAP
event.

This test tests raw reassembly inspection of unack'd data with GAP.
Binary file added tests/tcp-rst-unacked-stream-03-gap/input.pcap
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/tcp-rst-unacked-stream-03-gap/test.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alert tcp any any -> any any (content:"Me In"; sid:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; threshold:type backoff, track by_flow, count 1, multiplier 10; classtype:protocol-command-decode; sid:2210048; rev:3;)
18 changes: 18 additions & 0 deletions tests/tcp-rst-unacked-stream-03-gap/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

checks:
- filter:
count: 1
match:
event_type: alert
alert.signature_id: 1
pkt_src: "stream (flow timeout)"
- filter:
count: 0
match:
event_type: alert
alert.signature_id: 2210048
- filter:
count: 1
match:
event_type: stats
stats.tcp.reassembly_gap: 0
15 changes: 15 additions & 0 deletions tests/tcp-rst-unacked-stream-03-gap/writepcap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python
from scapy.all import *

pkts = []

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='S',seq=1,options=[('WScale', 14)])
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='SA',seq=1000,ack=2,options=[('WScale', 14)],window=65535)
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1001,ack=2,window=65535)/"Please "
#pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1008,ack=2,window=65535)/"Let "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1012,ack=2,window=65535)/"Me "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1015,ack=2,window=65535)/"In!"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='RA',seq=2,ack=1008,window=65535)/"Access Denied"

wrpcap('input.pcap', pkts)
8 changes: 8 additions & 0 deletions tests/tcp-rst-unacked-stream-04-gap-ips/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Test
====

Test series that tests if a RST that comes in before all data is ACK'd the
unACK'd data is still reassembled and inspected, but does not trigger a GAP
event.

This test tests raw reassembly inspection of unack'd data with GAP in IPS mode.
Binary file added tests/tcp-rst-unacked-stream-04-gap-ips/input.pcap
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/tcp-rst-unacked-stream-04-gap-ips/test.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alert tcp any any -> any any (content:"Me In"; sid:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; threshold:type backoff, track by_flow, count 1, multiplier 10; classtype:protocol-command-decode; sid:2210048; rev:3;)
18 changes: 18 additions & 0 deletions tests/tcp-rst-unacked-stream-04-gap-ips/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

checks:
- filter:
count: 1
match:
event_type: alert
alert.signature_id: 1
pcap_cnt: 6
- filter:
count: 0
match:
event_type: alert
alert.signature_id: 2210048
- filter:
count: 1
match:
event_type: stats
stats.tcp.reassembly_gap: 0
15 changes: 15 additions & 0 deletions tests/tcp-rst-unacked-stream-04-gap-ips/writepcap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python
from scapy.all import *

pkts = []

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='S',seq=1,options=[('WScale', 14)])
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='SA',seq=1000,ack=2,options=[('WScale', 14)],window=65535)
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1001,ack=2,window=65535)/"Please "
#pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1008,ack=2,window=65535)/"Let "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1012,ack=2,window=65535)/"Me "
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='AP',seq=1015,ack=2,window=65535)/"In!"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='RA',seq=2,ack=1001,window=65535)/"Access Denied"

wrpcap('input.pcap', pkts)
8 changes: 8 additions & 0 deletions tests/tcp-rst-unacked-stream-05-http-nogap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Test
====

Test series that tests if a RST that comes in before all data is ACK'd the
unACK'd data is still reassembled and inspected, but does not trigger a GAP
event.

This test tests HTTP reassembly inspection of unack'd data w/o GAP.
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/tcp-rst-unacked-stream-05-http-nogap/test.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alert tcp any any -> any any (content:"User-Agent: Mozilla"; sid:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; threshold:type backoff, track by_flow, count 1, multiplier 10; classtype:protocol-command-decode; sid:2210048; rev:3;)
18 changes: 18 additions & 0 deletions tests/tcp-rst-unacked-stream-05-http-nogap/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

checks:
- filter:
count: 1
match:
event_type: alert
alert.signature_id: 1
pkt_src: "stream (flow timeout)"
- filter:
count: 0
match:
event_type: alert
alert.signature_id: 2210048
- filter:
count: 1
match:
event_type: stats
stats.tcp.reassembly_gap: 0
17 changes: 17 additions & 0 deletions tests/tcp-rst-unacked-stream-05-http-nogap/writepcap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env python
from scapy.all import *

pkts = []

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='S',seq=1,options=[('WScale', 14)])
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='SA',seq=1000,ack=2,options=[('WScale', 14)],window=65535)
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)/"GET / HTTP/1.0\r\n"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=18,ack=1001,window=65535)/"Cookie: abcdef\r\n"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=34,ack=1001,window=65535)/"User-Agent: "
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=46,ack=1001,window=65535)/"Mozilla\r\n\r\n"

pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='RA',seq=1001,ack=18,window=65535)

wrpcap('input.pcap', pkts)
8 changes: 8 additions & 0 deletions tests/tcp-rst-unacked-stream-06-http-nogap-ips/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Test
====

Test series that tests if a RST that comes in before all data is ACK'd the
unACK'd data is still reassembled and inspected, but does not trigger a GAP
event.

This test tests HTTP reassembly inspection of unack'd data w/o GAP in IPS mode.
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/tcp-rst-unacked-stream-06-http-nogap-ips/test.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alert tcp any any -> any any (content:"User-Agent: Mozilla"; sid:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; threshold:type backoff, track by_flow, count 1, multiplier 10; classtype:protocol-command-decode; sid:2210048; rev:3;)
18 changes: 18 additions & 0 deletions tests/tcp-rst-unacked-stream-06-http-nogap-ips/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

checks:
- filter:
count: 1
match:
event_type: alert
alert.signature_id: 1
pcap_cnt: 7
- filter:
count: 0
match:
event_type: alert
alert.signature_id: 2210048
- filter:
count: 1
match:
event_type: stats
stats.tcp.reassembly_gap: 0
17 changes: 17 additions & 0 deletions tests/tcp-rst-unacked-stream-06-http-nogap-ips/writepcap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env python
from scapy.all import *

pkts = []

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='S',seq=1,options=[('WScale', 14)])
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='SA',seq=1000,ack=2,options=[('WScale', 14)],window=65535)
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)/"GET / HTTP/1.0\r\n"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=18,ack=1001,window=65535)/"Cookie: abcdef\r\n"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=34,ack=1001,window=65535)/"User-Agent: "
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=46,ack=1001,window=65535)/"Mozilla\r\n\r\n"

pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='RA',seq=1001,ack=18,window=65535)

wrpcap('input.pcap', pkts)
8 changes: 8 additions & 0 deletions tests/tcp-rst-unacked-stream-07-http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Test
====

Test series that tests if a RST that comes in before all data is ACK'd the
unACK'd data is still reassembled and inspected, but does not trigger a GAP
event.

This test tests HTTP reassembly inspection of unack'd data with GAP.
Binary file added tests/tcp-rst-unacked-stream-07-http/input.pcap
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/tcp-rst-unacked-stream-07-http/test.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alert tcp any any -> any any (content:"User-Agent: Mozilla"; sid:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; threshold:type backoff, track by_flow, count 1, multiplier 10; classtype:protocol-command-decode; sid:2210048; rev:3;)
18 changes: 18 additions & 0 deletions tests/tcp-rst-unacked-stream-07-http/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

checks:
- filter:
count: 1
match:
event_type: alert
alert.signature_id: 1
pkt_src: "stream (flow timeout)"
- filter:
count: 0
match:
event_type: alert
alert.signature_id: 2210048
- filter:
count: 1
match:
event_type: stats
stats.tcp.reassembly_gap: 0
17 changes: 17 additions & 0 deletions tests/tcp-rst-unacked-stream-07-http/writepcap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env python
from scapy.all import *

pkts = []

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='S',seq=1,options=[('WScale', 14)])
pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='SA',seq=1000,ack=2,options=[('WScale', 14)],window=65535)
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)

pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=2,ack=1001,window=65535)/"GET / HTTP/1.0\r\n"
#pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=18,ack=1001,window=65535)/"Cookie: abcdef\r\n"
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=34,ack=1001,window=65535)/"User-Agent: "
pkts += Ether(dst='05:04:03:02:01:00', src='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(src='1.1.1.1', dst='2.2.2.2')/TCP(dport=8080,sport=12345,flags='A',seq=46,ack=1001,window=65535)/"Mozilla\r\n\r\n"

pkts += Ether(src='05:04:03:02:01:00', dst='00:01:02:03:04:05')/Dot1Q(vlan=6)/IP(dst='1.1.1.1', src='2.2.2.2')/TCP(sport=8080,dport=12345,flags='RA',seq=1001,ack=18,window=65535)

wrpcap('input.pcap', pkts)
8 changes: 8 additions & 0 deletions tests/tcp-rst-unacked-stream-08-http-ips/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Test
====

Test series that tests if a RST that comes in before all data is ACK'd the
unACK'd data is still reassembled and inspected, but does not trigger a GAP
event.

This test tests HTTP reassembly inspection of unack'd data with GAP in IPS mode.
Binary file added tests/tcp-rst-unacked-stream-08-http-ips/input.pcap
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/tcp-rst-unacked-stream-08-http-ips/test.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alert tcp any any -> any any (content:"User-Agent: Mozilla"; sid:1;)
alert tcp any any -> any any (msg:"SURICATA STREAM reassembly sequence GAP -- missing packet(s)"; stream-event:reassembly_seq_gap; threshold:type backoff, track by_flow, count 1, multiplier 10; classtype:protocol-command-decode; sid:2210048; rev:3;)
18 changes: 18 additions & 0 deletions tests/tcp-rst-unacked-stream-08-http-ips/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

checks:
- filter:
count: 1
match:
event_type: alert
alert.signature_id: 1
pcap_cnt: 6
- filter:
count: 0
match:
event_type: alert
alert.signature_id: 2210048
- filter:
count: 1
match:
event_type: stats
stats.tcp.reassembly_gap: 0
Loading

0 comments on commit a582ae0

Please sign in to comment.