--- /dev/null
+## Description
+Test multiple pipelined http transactions.
+
+https://redmine.openinfosecfoundation.org/issues/6146
+
+## PCAP
+PCAP file generated by passing the `input.t` file to python2 `htptopcap.py` script in engine-state folder; as in `python2 htptopcap.py input.t`.
\ No newline at end of file
--- /dev/null
+>>>
+POST / HTTP/1.0
+
+>>>
+User-Agent: Mozilla/1.0
+Content-Length: 10
+
+>>>
+Cookie: dummy
+
+
+>>>
+Http Body!
+>>>
+GET /?var=val HTTP/1.1
+
+>>>
+User-Agent: Firefox/1.0
+
+>>>
+Cookie: dummy2
+Content-Length: 10
+
+Http Body!
+<<<
--- /dev/null
+alert tcp any any -> any any (content:"POST"; http_method; content:"dummy"; http_cookie; sid:1; rev:1;)
+alert tcp any any -> any any (flow:to_server; content:"POST"; http_method; content:"/"; http_uri; content:"Mozilla"; http_header; content:"dummy"; http_cookie; content:"body"; nocase; http_client_body; sid:2; rev:1;)
+alert tcp any any -> any any (flow:to_server; content:"GET"; http_method; content:"Firefox"; http_header; content:"dummy2"; http_cookie; sid:3; rev:1;)
--- /dev/null
+requires:
+ min-version: 7
+args:
+- -k none
+- --set stream.midstream=true
+
+checks:
+- filter:
+ count: 1
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 1
+
+- filter:
+ count: 1
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 2
+
+- filter:
+ count: 1
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 3
+
+- filter:
+ count: 1
+ match:
+ event_type: flow
--- /dev/null
+## Description
+Test state-based signature handling using the filestore and filename keyword.
+
+https://redmine.openinfosecfoundation.org/issues/6146
+
+## PCAP
+PCAP file generated by passing the `input.t` file to python2 `htptopcap.py` script in engine-state folder; as in `python2 htptopcap.py input.t`.
\ No newline at end of file
--- /dev/null
+>>>\r
+POST /upload.cgi HTTP/1.1\r
+Host: www.server.lan\r
+Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r
+Content-Length: 215\r
+\r
+-----------------------------277531038314945\r
+Content-Disposition: form-data; name="uploadfile_0"; filename="somepicture1.jpg"\r
+Content-Type: image/jpeg\r
+\r
+filecontent\r
+-----------------------------277531038314945--\r
+<<<
\ No newline at end of file
--- /dev/null
+%YAML 1.1
+---
+
+outputs:
+ - eve-log:
+ enabled: yes
+ types:
+ - files
+ - stats
+ - http
+ - alert
+ - flow
+ - file-store:
+ version: 2
+ enabled: yes
+ stream-depth: 0
+ write-fileinfo: true
\ No newline at end of file
--- /dev/null
+alert http any any -> any any (flow:to_server; content:"POST"; http_method; content:"upload.cgi"; http_uri; filestore; sid:1; rev:1;)
+alert http any any -> any any (content:"GET"; http_method; content:"upload.cgi"; http_uri; filestore; sid:2; rev:1;)
+alert http any any -> any any (content:"GET"; http_method; content:"upload.cgi"; http_uri; filename:"nomatch"; sid:3; rev:1;)
+alert http any any -> any any (content:"POST"; http_method; content:"upload.cgi"; http_uri; filename:"nomatch"; filestore; sid:4; rev:1;)
\ No newline at end of file
--- /dev/null
+requires:
+ min-version: 7
+args:
+- -k none
+- --set stream.midstream=true
+
+checks:
+- filter:
+ count: 1
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 1
+
+- filter:
+ count: 0
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 2
+
+- filter:
+ count: 0
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 3
+
+- filter:
+ count: 0
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 4
+
+- filter:
+ count: 1
+ match:
+ event_type: http
+
+- filter:
+ count: 1
+ match:
+ event_type: flow
\ No newline at end of file
--- /dev/null
+## Description
+Test that, file not stored if rule alert not triggered.
+
+https://redmine.openinfosecfoundation.org/issues/6146
+
+## PCAP
+PCAP file generated by passing the `input.t` file to python2 `htptopcap.py` script in engine-state folder; as in `python2 htptopcap.py input.t`.
\ No newline at end of file
--- /dev/null
+>>>\r
+POST /upload.cgi HTTP/1.1\r
+Host: www.server.lan\r
+Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r
+Content-Length: 215\r
+\r
+-----------------------------277531038314945\r
+Content-Disposition: form-data; name="uploadfile_0"; filename="somepicture1.jpg"\r
+Content-Type: image/jpeg\r
+\r
+\r
+>>>\r
+filecontent\r
+-----------------------------277531038314945--\r
+<<<
\ No newline at end of file
--- /dev/null
+%YAML 1.1
+---
+
+outputs:
+ - eve-log:
+ enabled: yes
+ types:
+ - files
+ - stats
+ - http
+ - alert
+ - flow
+ - file-store:
+ version: 2
+ enabled: yes
+ stream-depth: 0
+ write-fileinfo: true
\ No newline at end of file
--- /dev/null
+alert http any any -> any any (content:"GET"; http_method; content:"upload.cgi"; http_uri; filestore; sid:1; rev:1;)
\ No newline at end of file
--- /dev/null
+requires:
+ min-version: 7
+args:
+- -k none
+- --set stream.midstream=true
+
+checks:
+
+- filter:
+ count: 1
+ match:
+ event_type: fileinfo
+ has-key: flow_id
+
+- filter:
+ count: 1
+ match:
+ event_type: stats
+
+- filter:
+ count: 0
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 1
+
+- filter:
+ count: 1
+ match:
+ event_type: flow
+
+- shell:
+ args: test ! -e filestore/5a/5ab24eb0866bafe7d8c0d07f03f09aef7a4caa991a9dc1edd96e64683b750fe2
--- /dev/null
+## Description
+Test multiple files in a tx.
+
+https://redmine.openinfosecfoundation.org/issues/6146
+
+## PCAP
+PCAP file generated by passing the `input.t` file to python2 `htptopcap.py` script in engine-state folder; as in `python2 htptopcap.py input.t`.
\ No newline at end of file
--- /dev/null
+>>>\r
+POST /upload.cgi HTTP/1.1\r
+Host: www.server.lan\r
+Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r
+Content-Length: 385\r
+\r
+-----------------------------277531038314945\r
+Content-Disposition: form-data; name="uploadfile_0"; filename="AAAApicture1.jpg"\r
+Content-Type: image/jpeg\r
+\r
+\r
+>>>\r
+file\r
+>>>\r
+content\r
+-----------------------------277531038314945\r
+\r
+>>>\r
+Content-Disposition: form-data; name="uploadfile_1"; filename="BBBBpicture2.jpg"\r
+Content-Type: image/jpeg\r
+\r
+filecontent2\r
+-----------------------------277531038314945--\r
+<<<
\ No newline at end of file
--- /dev/null
+%YAML 1.1
+---
+
+outputs:
+ - eve-log:
+ enabled: yes
+ types:
+ - files
+ - stats
+ - http
+ - alert
+ - flow
+ - file-store:
+ version: 2
+ enabled: yes
+ stream-depth: 0
+ write-fileinfo: true
\ No newline at end of file
--- /dev/null
+alert http any any -> any any (content:"POST"; http_method; content:"upload.cgi"; http_uri; filename:"BBBBpicture"; filestore; sid:1; rev:1;)
\ No newline at end of file
--- /dev/null
+requires:
+ min-version: 7
+args:
+- -k none
+- --set stream.midstream=true
+
+checks:
+
+- filter:
+ count: 1
+ match:
+ event_type: alert
+ alert.action: allowed
+ alert.signature_id: 1
+
+- filter:
+ count: 1
+ match:
+ event_type: http
+
+- filter:
+ count: 1
+ match:
+ event_type: flow
+ flow.alerted: true
+
+- shell:
+ args: test -e filestore/ec/ec3a53b52eb11808d59d29ffd01568edf2d62cdc9c02def84d0a11704d552de2
\ No newline at end of file
--- /dev/null
+## Description
+Test multiple files in a tx.
+
+Both files should match; no other matches.
+
+https://redmine.openinfosecfoundation.org/issues/6146
+
+## PCAP
+PCAP file generated by passing the `input.t` file to python2 `htptopcap.py` script in engine-state folder; as in `python2 htptopcap.py input.t`.
\ No newline at end of file
--- /dev/null
+>>>\r
+POST /upload.cgi HTTP/1.1\r
+Host: www.server.lan\r
+Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r
+Content-Length: 385\r
+\r
+-----------------------------277531038314945\r
+Content-Disposition: form-data; name="uploadfile_0"; filename="somepicture1.jpg"\r
+Content-Type: image/jpeg\r
+\r
+\r
+>>>\r
+file\r
+>>>\r
+content\r
+-----------------------------277531038314945\r
+\r
+>>>\r
+Content-Disposition: form-data; name="uploadfile_1"; filename="somepicture2.jpg"\r
+Content-Type: image/jpeg\r
+\r
+filecontent2\r
+-----------------------------277531038314945--\r
+<<<
\ No newline at end of file
--- /dev/null
+%YAML 1.1
+---
+
+outputs:
+ - eve-log:
+ enabled: yes
+ types:
+ - files
+ - stats
+ - http
+ - alert
+ - flow
+ - file-store:
+ version: 2
+ enabled: yes
+ stream-depth: 0
+ write-fileinfo: true
\ No newline at end of file
--- /dev/null
+alert http any any -> any any (content:"POST"; http_method; content:"upload.cgi"; http_uri; filename:"somepicture"; filestore; sid:1; rev:1;)
+alert http any any -> any any (filename:"somepicture"; filestore; sid:2; rev:1;)
\ No newline at end of file
--- /dev/null
+requires:
+ min-version: 7
+args:
+- -k none
+- --set stream.midstream=true
+
+checks:
+- filter:
+ count: 1
+ match:
+ alert.action: allowed
+ alert.signature_id: 1
+ event_type: alert
+ files[0].filename: somepicture1.jpg
+
+- filter:
+ count: 1
+ match:
+ alert.action: allowed
+ alert.signature_id: 2
+ event_type: alert
+ files[0].filename: somepicture1.jpg
+
+- shell:
+ args: test -e filestore/5a/5ab24eb0866bafe7d8c0d07f03f09aef7a4caa991a9dc1edd96e64683b750fe2
+
+- filter:
+ count: 1
+ match:
+ alert.action: allowed
+ alert.signature_id: 1
+ event_type: alert
+ files[0].filename: somepicture2.jpg
+
+- filter:
+ count: 1
+ match:
+ alert.action: allowed
+ alert.signature_id: 2
+ event_type: alert
+ files[0].filename: somepicture2.jpg
+
+- shell:
+ args: test -e filestore/ec/ec3a53b52eb11808d59d29ffd01568edf2d62cdc9c02def84d0a11704d552de2
+
+- filter:
+ count: 1
+ match:
+ event_type: http
+
+- filter:
+ count: 1
+ match:
+ event_type: flow
\ No newline at end of file
--- /dev/null
+#! /usr/bin/env python
+
+# @author: Philippe Antoine
+
+import sys
+import binascii
+from threading import Thread
+import time
+import socket
+
+# Create a pcap from a htp test file
+# Launches a server on port 8080
+# Launches a client in another thread that connects to it
+# Both client and server read the htp test file
+# And they send and receive data as described (without analysing it)
+# So, you need to capture traffic on port 8080 while running the script
+
+def removeOneEOL(s):
+ r = s
+ if r[-1] == '\n':
+ r = r[:-1]
+ if r[-1] == '\r':
+ r = r[:-1]
+ return r
+
+
+class ServerThread(Thread):
+
+ def __init__(self, filename):
+ Thread.__init__(self)
+ self.filename = filename
+
+ def run(self):
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.bind(("127.0.0.1", 8080))
+ s.listen(1)
+ conn, addr = s.accept()
+ f = open(self.filename)
+ state = 0
+ sending = ""
+ receiving = ""
+
+ for l in f.readlines():
+ # change of state
+ if l.rstrip() == "<<<" or l.rstrip() == ">>>":
+ # Receiving or sending buffer
+ if state == 1:
+ conn.send(removeOneEOL(sending))
+ print "server sent", len(removeOneEOL(sending))
+ elif state == 2:
+ data = conn.recv(len(removeOneEOL(receiving)))
+ print "server recvd", len(data)
+ if l.rstrip() == "<<<":
+ state = 1
+ sending = ""
+ elif l.rstrip() == ">>>":
+ state = 2
+ receiving = ""
+ else:
+ if state == 1:
+ sending += l
+ elif state == 2:
+ receiving += l
+
+ # Receiving or sending last buffer
+ if state == 1:
+ conn.send(sending)
+ print "server sent", len(sending)
+ elif state == 2:
+ data = conn.recv(len(receiving))
+ print "server recvd", len(data)
+ conn.close()
+ s.close()
+ f.close()
+
+
+class ClientThread(Thread):
+
+ def __init__(self, filename):
+ Thread.__init__(self)
+ self.filename = filename
+
+ def run(self):
+ time.sleep(1)
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect(("127.0.0.1", 8080))
+ f = open(self.filename)
+ state = 0
+ sending = ""
+ receiving = ""
+
+ for l in f.readlines():
+ if l.rstrip() == "<<<" or l.rstrip() == ">>>":
+ if state == 1:
+ s.send(removeOneEOL(sending))
+ print "client sent", len(removeOneEOL(sending))
+ elif state == 2:
+ data = s.recv(len(removeOneEOL(receiving)))
+ print "client recvd", len(data)
+ if l.rstrip() == "<<<":
+ state = 2
+ receiving = ""
+ elif l.rstrip() == ">>>":
+ state = 1
+ sending = ""
+ else:
+ if state == 1:
+ sending += l
+ elif state == 2:
+ receiving += l
+
+ if state == 1:
+ s.send(sending)
+ print "client sent", len(sending)
+ elif state == 2:
+ data = s.recv(len(receiving))
+ print "client recvd", len(data)
+ s.close()
+ f.close()
+
+t1 = ServerThread(sys.argv[1])
+t2 = ClientThread(sys.argv[1])
+
+# Launch threads
+t1.start()
+t2.start()
+
+# Wait for threads to finish
+t1.join()
+t2.join()