Test how the signature framework matches HTTP body

This adds a signatures/http-body-match btest to verify how the signature
framework matches HTTP body in requests and responses.

It currently fails because the 'http-request-body' and 'http-reply-body'
clauses never match anything when there is a '$' in their regular
expressions.

The other pattern clauses such as the 'payload' clause do not suffer
from that restriction and it is not documented as a limitation of HTTP
body pattern clauses either, so it is probably a bug.

The "http-body-match" btest shows that without a fix any signatures
which ends with a '$' in a http-request-body or http-reply-body rule
will never raise a signature_match() event, and that signatures which do
not end with a '$' cannot distinguish an HTTP body prefixed by the
matching pattern (ex: ABCD) from an HTTP body consisting entirely of the
matching pattern (ex: AB).

Test cases by source port:
- 13579:
  - GET without body, plain res body (CD, only)
- 13578:
  - GET without body, plain res body (CDEF, prefix)
- 24680:
  - POST plain req body (AB, only), plain res body (CD, only)
- 24681:
  - POST plain req body (ABCD, prefix), plain res body (CDEF, prefix)
- 24682:
  - POST gzipped req body (AB, only), gzipped res body (CD, only)
  - POST plain req body (CD, only), plain res body (EF, only)
- 33210:
  - POST multipart plain req body (AB;CD;EF, prefix)
  - plain res body (CD, only)
- 33211:
  - POST multipart plain req body (ABCD;EF, prefix)
  - plain res body (CDEF, prefix)
- 34527:
  - POST chunked gzipped req body (AB, only)
  - chunked gzipped res body (CD, only)
- 34528:
  - POST chunked gzipped req body (ABCD, prefix)
  - chunked gzipped res body (CDEF, prefix)

The tests with source ports 24680, 24682 and 34527 should
match the signature http_request_body_AB_only and the signature
http_request_body_AB_prefix, but they only match the latter.

The tests with source ports 13579, 24680, 24682, 33210 and 34527 should
match the signature http_response_body_CD_only and the signature
http_response_body_CD_prefix, but they only match the latter.

The tests with source ports 24680, 24681, 33210 and 33211 show how the
http_request_body_AB_then_CD signature with two http-request-body
conditions match either on one or multiple requests (documented
behaviour).

The test cases with other source ports show where the
http_request_body_AB_only and http_response_body_CD_only signatures
should not match because their bodies include more than the searched
patterns.
This commit is contained in:
xb-anssi 2023-11-02 17:09:56 +01:00
parent 4eb1b71d1b
commit c8103dd963
No known key found for this signature in database
GPG key ID: 08AAE5775A62F923
3 changed files with 70 additions and 0 deletions

View file

@ -0,0 +1,27 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
HTTP body match for 192.0.2.42:13578 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'D'
HTTP body match for 192.0.2.42:13579 -> 192.88.99.42:80 with signature 'http_response_body_CD_only', data: ''
HTTP body match for 192.0.2.42:13579 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'D'
HTTP body match for 192.0.2.42:24680 -> 192.88.99.42:80 with signature 'http_request_body_AB_only', data: ''
HTTP body match for 192.0.2.42:24680 -> 192.88.99.42:80 with signature 'http_request_body_AB_prefix', data: 'B'
HTTP body match for 192.0.2.42:24680 -> 192.88.99.42:80 with signature 'http_response_body_CD_only', data: ''
HTTP body match for 192.0.2.42:24680 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'D'
HTTP body match for 192.0.2.42:24681 -> 192.88.99.42:80 with signature 'http_request_body_AB_prefix', data: 'B'
HTTP body match for 192.0.2.42:24681 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'D'
HTTP body match for 192.0.2.42:24682 -> 192.88.99.42:80 with signature 'http_request_body_AB_only', data: ''
HTTP body match for 192.0.2.42:24682 -> 192.88.99.42:80 with signature 'http_request_body_AB_prefix', data: 'AB'
HTTP body match for 192.0.2.42:24682 -> 192.88.99.42:80 with signature 'http_request_body_AB_then_CD', data: 'CD'
HTTP body match for 192.0.2.42:24682 -> 192.88.99.42:80 with signature 'http_response_body_CD_only', data: ''
HTTP body match for 192.0.2.42:24682 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'CD'
HTTP body match for 192.0.2.42:33210 -> 192.88.99.42:80 with signature 'http_request_body_AB_prefix', data: 'AB'
HTTP body match for 192.0.2.42:33210 -> 192.88.99.42:80 with signature 'http_request_body_AB_then_CD', data: 'CD'
HTTP body match for 192.0.2.42:33210 -> 192.88.99.42:80 with signature 'http_response_body_CD_only', data: ''
HTTP body match for 192.0.2.42:33210 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'D'
HTTP body match for 192.0.2.42:33211 -> 192.88.99.42:80 with signature 'http_request_body_AB_prefix', data: 'ABCD'
HTTP body match for 192.0.2.42:33211 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'D'
HTTP body match for 192.0.2.42:34527 -> 192.88.99.42:80 with signature 'http_request_body_AB_only', data: ''
HTTP body match for 192.0.2.42:34527 -> 192.88.99.42:80 with signature 'http_request_body_AB_prefix', data: 'AB'
HTTP body match for 192.0.2.42:34527 -> 192.88.99.42:80 with signature 'http_response_body_CD_only', data: ''
HTTP body match for 192.0.2.42:34527 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'CD'
HTTP body match for 192.0.2.42:34528 -> 192.88.99.42:80 with signature 'http_request_body_AB_prefix', data: 'ABCD'
HTTP body match for 192.0.2.42:34528 -> 192.88.99.42:80 with signature 'http_response_body_CD_prefix', data: 'CDEF'

Binary file not shown.

View file

@ -0,0 +1,43 @@
# @TEST-EXEC: zeek -b -r $TRACES/http/http-body-match.pcap %INPUT | sort >out
# @TEST-EXEC: btest-diff out
@load-sigs test.sig
@load base/protocols/http
@TEST-START-FILE test.sig
signature http_request_body_AB_prefix {
http-request-body /^AB/
event "HTTP request body starting with AB"
}
signature http_request_body_AB_only {
http-request-body /^AB$/
event "HTTP request body containing AB only"
}
signature http_request_body_AB_then_CD {
http-request-body /AB/
http-request-body /CD/
event "HTTP request body containing AB and CD, but maybe not be on same request (documented behaviour)"
}
signature http_response_body_CD_prefix {
http-reply-body /^CD/
event "HTTP response body starting with CD"
}
signature http_response_body_CD_only {
http-reply-body /^CD$/
event "HTTP response body containing CD only"
}
@TEST-END-FILE
event signature_match(state: signature_state, msg: string, data: string)
{
print(fmt("HTTP body match for %s:%d -> %s:%d with signature '%s', data: '%s'",
state$conn$id$orig_h, state$conn$id$orig_p,
state$conn$id$resp_h, state$conn$id$resp_p,
state$sig_id,
data
));
}