Commit Graph

2137 Commits (main-8.0.x)

Author SHA1 Message Date
Jason Ish 8461dbc9a5 http2: test continuation progress on the 8.0.x state machine
Cover split END_STREAM headers in both directions, with and without an
already-closed peer, intermediate continuations, normal headers and DATA,
and duplicate end-of-stream handling.

Require a matching stream before inheriting the reassembly buffer's saved
END_STREAM flag. Otherwise an orphan continuation on stream B can inherit
stream A's flag and prematurely close B. Test that the orphan raises the
anomaly without consuming A's pending flag, then complete A normally.

Ticket: #9218
3 days ago
Philippe Antoine f7ceb8134b http2: anomaly event on continuation frame without preceding headers
Ticket: 9217
(cherry picked from commit 0a48101ba0)
3 days ago
Philippe Antoine 1a532d7fd3 http2: update progress after continuation frame ended stream
Ticket: 9217

Backport note: Feed the saved END_STREAM flag from CONTINUATION frames
through the existing 8.0.x half-closed/closed transaction-state transitions,
without importing main's per-direction progress tracking. Retain the
upstream header-reassembly and continuation-parser changes unchanged.

(cherry picked from commit 620dff6759)
3 days ago
Philippe Antoine a12e64da94 http2: do not update progress on END_STREAM without END_HEADERS
As more continuation frames are expected.
Next commit will update progress for those continuation frames.

Ticket: 9217

Backport note: Gate the existing 8.0.x transaction-state transition on
END_HEADERS for HEADERS frames, preserving DATA and half-closed handling
instead of importing main's per-direction progress state machines.

(cherry picked from commit ef7184012a)
3 days ago
Shivani Bhardwaj fc88ba764f rust: update clipboard-win
clipboard-win versions 5.2.0 - 5.4.1 were yanked by the author on
crates.io index. Use the latest available version instead.
4 days ago
Shivani Bhardwaj 9d217f1ec6 detect/flow-pkts: check for both dir
The functionality of "both" can already be easily achieved by using both
"toclient" and "toserver" in a rule. This just adds the ease of
expression in rule. As it is added now, check the direction for the
pre-existing users of direction as well.

(cherry picked from commit 06eafb79d6)
4 days ago
Shivani Bhardwaj 2efa800bae rust/flow: add public wrapper for dir
in order to be able to use it on the C side for elephant flow detection.

(cherry picked from commit 77abcde9ee)
4 days ago
Philippe Antoine 41dfa01e5f http1: only disable decompression after too many bombs
Ticket: 9200

And to do so, reinit the content_encoding, so that
we do not try to take a decompressor

(cherry picked from commit 37cc354809)
1 week ago
Philippe Antoine 9deac541b7 datasets: do not accept char devices
Such as /dev/zero

Ticket: 9106
(cherry picked from commit 46aa14f61c)
1 week ago
Jason Ish 1823f1b5e8 psl: update to 2.1.241
Update the embedded public suffix list for the upcoming 8.0.8 release.

Ticket: 9031
1 week ago
Amir Boussejra 77f02f8291 ftp: log completion code when the response message is empty
A response line carrying a code but no message, such as "221 \r\n" sent by
some servers in reply to QUIT, was logged with no completion_code, and with
the code itself in the reply field:

    {"command": "QUIT", "reply": ["221"], "reply_received": "yes"}

parse_response_line split caused problems on no response message and prevented good logging of completion code

Ticket: #8966
(cherry picked from commit 23ff7feebb)
1 week ago
Shivani Bhardwaj b502742db7 datasets: accept standard IPv4 notation for ip type
The internal type set for datasets of type IP is IPv6, however, the
expectation is that it'll support IPv6, standard IPv4 as well as IPv4 in
IPv6 notation. A regression happened during the conversion of datasets
parsing to rust wherein standard IPv4 was rejected with IP type. Fix
that by handling IPv4 standard notation in IPv6 handler.

Fixes: bc79300dfa ("datasets: move initial file reading to rust")

Ticket: 9006
(cherry picked from commit 8b379a3b04)
3 weeks ago
Victor Julien 221d7d33f0 rust: drop block-wrapped scrutinees rejected by clippy 1.99
block_scrutinee now warns on a block-wrapped if let scrutinee, since
the block changes when temporaries drop. The file config reads in the
nfs, smb and http2 gettxfiles handlers were wrapped in a pointless
single-expression block; remove it.
3 weeks ago
Philippe Antoine b4c9c8db35 http1: keep monotonic progress for 100-continue
Ticket: 9096

In case of a 100-continue response, we used to
- parse the response line, set progress to headers
- parse headers, set progress back to line

This caused FPs as the engine expects the progress to just increase
so that it skips signatures that did not match yet, and whose
progress is less than the tx progress.

Solution is to keep progress at line when we see a 100 response,
until we get to the body, or after a next response line which
is not 100.

(cherry picked from commit 65d2df795f)
4 weeks ago
Juliana Fajardini 6dee1b26a6 pgsql: add notice about parser default enabling
As it may be unexpected that removing app-layer.protocols.pgsql.enabled
or the pgsql section altogether from the settings actually enables the
parser, inform users of this when it happens.

Ticket: #8350
4 weeks ago
Philippe Antoine 2a302edec9 app-layer: function to register ci pattern + probe
Ticket: 6591
(cherry picked from commit 7dbe033ae0)
1 month ago
Giuseppe Longo a5ec4419e3 nfs: fix clippy errors 1 month ago
Victor Julien 4f41bbbbe6 version: start development towards 8.0.8 1 month ago
Jason Ish d681600f36 release: 8.0.7; update changelog 1 month ago
Victor Julien f1c57152d0 smb: cap the OOO gap backstop by chunk count and inspect all open files
The byte backstop leaves many tiny OOO chunks unbounded, and the scan
only inspected the in-progress file, which an interleaved second
handle could hide. Add a chunk-count backstop (configured count, 1024
hard cap when disabled) and check every open file tx.

Ticket: #8791.
(cherry picked from commit a4e4c3cd7b)
1 month ago
Victor Julien 4fa69705f8 smb: rework the OOO file-data gap backstop to the queue limits
Replace the hardcoded 2 MiB gap backstop, which silently truncated
OOO file data, with the configured queue size per direction (1 GiB
hard cap when disabled), raising SMBEvent::TruncatedFileData. It runs
ahead of the chunk_left == 0 early return, and a gap reaching the
tracker tags the session gapped even when fully consumed.

Ticket: #8791.
(cherry picked from commit 3c9883b37c)
1 month ago
Victor Julien ca0d780fd5 smb: enforce the write/read queue limits
The SMB1 WRITE_ANDX/READ_ANDX handlers fed the file tracker
unconditionally and SMB2 only checked raw in-flight occupancy. Apply
the max-{read,write}-queue-{size,cnt} checks, projected onto actual
queue growth, to both protocols' found and create-new tx branches;
on overflow raise the queue event and skip the record's remainder.

Ticket: #8791.
(cherry picked from commit b39984c87e)
1 month ago
Victor Julien 7ab8ba7b97 nfs: bound the chunk-continuation stream skip by the record tail
The chunk-continuation queue-limit rejection accounted its stream
consumption and skip from the count-based chunk promise
(chunk_left), but the parser accepts file_len < count and the
tracker only ever consumes file_len bytes. With count > file_len
the consume/skip ran past the record's actual tail into the
following RPC record and the stream desynced.

Consume/skip from the record's unbuffered tail plus the record's
XDR padding.

Ticket: #8791.
(cherry picked from commit 96d943d1c1)
1 month ago
Victor Julien 1f407fdd3e nfs: rework and cap the OOO gap backstop to the queue limits
Rework the queue-limit gap backstop: fall back to a 1 GiB / 1024
chunk hard cap when the limits are disabled, run it ahead of the
chunk_left == 0 early return, and scan every open file tx in the
direction (an interleaved handle can hide a first file's queue).
TruncatedFileData is attributed to the truncated tx.

Ticket: #8791.
(cherry picked from commit 36e8ff5082)
1 month ago
Victor Julien 26de470c2a nfs: enforce the OOO queue limits on the chunk path
The chunk path (filetracker_update) enqueued per-segment data with no
queue limit. Check the limits on every enqueuing path, projected onto
actual queue growth: only OOO data at a new offset grows the queue,
and only a new OOO chunk adds a map entry. Overflow raises the queue
event on the affected tx and skips to the record boundary.

Replace the 2 MiB gap backstop with a queue-limit one (the chunk-count
cap and all-open-file scan come next), and tag the session gapped on
every gap (even one fully covered by a skip), since the backstop is
gated on that flag. Rejected and evicted tx now release their file
resources so the file logger can clean them up.

Ticket: #8791.
(cherry picked from commit 3a37959005)
1 month ago
Victor Julien cb2dee7e9a nfs: validate WRITE and READ records sizes
Replace the hardcoded 16 MiB record caps with configurable
max-{write,read}-size and observable events: an oversized WRITE
request or READ response is rejected, logged, and its payload skipped
to keep the stream in sync. 0 disables the check.

For v4 records, the issue is more complex due to the COMPOUND type:
A partial v4 COMPOUND record whose frag_len claim is huge must not be
buffered toward that claim (31-bit, attacker-controlled → OOM). The
full parser can't help: on a partial buffer it only returns Incomplete
 ("need more bytes"), with no information about what's coming. The scan
instead walks the buffered prefix's ops by wire extent and reads the
file op's header words alone, answering the gate's four-way question:
 oversized claim detected (reject + skip to the record boundary before
any data buffers), data not yet present (buffer normally), structurall
malformed (bounded rejection), or no oversized op (fall through). It
exists because rejecting before buffering requires the claimed length,
which only a prefix walk can extract.

Ticket: #8791.
(cherry picked from commit 29a5370e71)
1 month ago
Victor Julien 0362baf024 nfs: enforce max read/write queue size and count limits
Bound the per-file-transaction OOO queue, mirroring SMB: add
max-{read,write}-queue-{size,cnt} (0 disables, default 64 MiB / 64),
raise a queue event on overflow, and skip the truncated record's
remainder from the stream.

Ticket: #8791.
(cherry picked from commit b8aeaebcbd)
1 month ago
Victor Julien 2d0af82a68 rust: update ldap parser
Ticket: #8793.
(cherry picked from commit 9a25b2d93e)
1 month ago
Philippe Antoine f24d639ad0 pgsql: fix clippy warning
Fixes fe939e8da7

(cherry picked from commit 368bfa6d1f)
2 months ago
Victor Julien 6a44949f96 http2: strip padding bytes from PADDED HEADERS/PUSH_PROMISE frames
When the PADDED flag is set on HTTP/2 HEADERS or PUSH_PROMISE frames,
the parser reads the 1-byte Pad Length field but never strips trailing
padding bytes before passing the buffer to the HPACK decoder.

Fix by stripping trailing padding before invoking the HPACK decoder.

Ticket: #8787.
(cherry picked from commit 2edba88a54)
2 months ago
Philippe Antoine 0794dc6a0a http2: improve continuation frame reassembly
by taking into account the flags of the first header frame,
and skip priority and padlength if necessary

Ticket: 8840
(cherry picked from commit 8e5d05f93f)
2 months ago
Giuseppe Longo 5ab8b5c241 swf: grow lzma output in one decoder pass
The on-demand buffer growth introduced for SWF decompression called
lzma_decompress again from byte zero each time the output buffer filled.
Because lzma-rs can buffer up to a dictionary before writing, a single
SWF could be decoded repeatedly as the buffer grew, amplifying CPU use.

This adds a depth-bounded Rust writer that asks C to grow the inspection
buffer as decompressed bytes are emitted.
This keeps a single lzma-rs stream alive, so the input is decoded only once.

Ticket: #8829
(cherry picked from commit d80d7f75a8)
2 months ago
Giuseppe Longo eda28fab8d swf: grow decompression buffer on demand
Previously, SWF decompression guessed the final output size from FileLength,
allocated the whole buffer, and then decompressed once. A malicious SWF could
claim a 50MB output and force the per-thread inspection buffer to allocate and
retain 64 MiB before the compressed data was even checked.

Change the logic:
allocate 4 KiB, decompress, grow only when the buffer is full, and continue.
The buffer grows geometrically up to the configured output limit,
and the final inspection length is set to the number of bytes actually produced.

Also, for zlib, Z_OK does not by itself mean that decompression is complete.
It should be checked together with avail_out and avail_in,
grow the buffer when output space is exhausted, and continue the same inflate stream.

Ticket: #8829
(cherry picked from commit ddc6d29fd1)
2 months ago
Giuseppe Longo 2899262fd2 sip: make pattern matching more robust
SIP and SSDP share method names like NOTIFY and SUBSCRIBE,
causing SSDP traffic to be misidentified as SIP.
Add a probing parser callback that checks for "SIP/" in the
payload before accepting a pattern match.

Example of a misidentified flow before the fix:
{"timestamp":"2014-02-27T19:44:43.164211+0100","flow_id":986757542077835,"event_type":"flow","src_ip":"192.168.1.1","src_port":9489,"dest_ip":"239.255.255.250
","dest_port":1900,"ip_v":4,"proto":"UDP","app_proto":"sip","flow":{"..."}}

After the fix:
{"timestamp":"2014-02-27T19:44:43.164211+0100","flow_id":986757542077835,"event_type":"flow","src_ip":"192.168.1.1","src_port":9489,"dest_ip":"239.255.255.250
","dest_port":1900,"ip_v":4,"proto":"UDP","app_proto":"failed","flow":{"..."}}

Ticket #8355

(cherry picked from commit ba5e850264)
2 months ago
Victor Julien 537e6ef154 nfs: fix allocation check in LAYOUTGET fh_handles
The check was too weak: it allowed fh_handles far beyond what fits
in the remaining input, letting a crafted packet drive a large
Vec::with_capacity preallocation in nom7 count().

Bound fh_handles by the remaining input size and by 4096, the
maximum file layout stripe count used by the Linux kernel
(NFS4_PNFS_MAX_STRIPE_CNT).

Ticket: #8816.
(cherry picked from commit f93d40bade)
2 months ago
Victor Julien 2d47fb1494 smb1: bound dialect count in NEGOTIATE_PROTOCOL parser
Negotiate protocol parser used an unbounded many1(complete(...))
combinator over the entire remaining packet input, discarding both
wct and bcc fields. Each NUL byte yielded one empty "dialect" entry,
causing excessive memory use.

Use bcc to limit the parsing; the dialect count is then bounded by
bcc (u16).

Ticket: #8852.
(cherry picked from commit ba1cafd34e)
2 months ago
Giuseppe Longo dad8363d8a dhcp: distinguish malformed and truncated options
This patch distinguishes malformed DHCP options from truncated ones.
Previously, the malformed_options field was never set and parsing errors in
overloaded file and sname fields were silently discarded.
This caused malformed options to be reported as truncated or not reported at all.

Classify errors in the primary option stream and overloaded fields.
Treat failures within fixed-size overloaded fields as malformed because those
fields are already fully present.

Ticket #8874

(cherry picked from commit e89b7644a8)
2 months ago
Giuseppe Longo 5b882dd0b3 dhcp: validate address time option lengths
DHCP lease, renewal, and rebinding time options contain a four-byte value,
but the parser previously ignored their declared length and always consumed
four bytes.

Reject these options unless their length is exactly four to
prevent parser desynchronization and incorrect keyword matches.

Ticket #8873

(cherry picked from commit 382b18da9b)
2 months ago
Giuseppe Longo f5d47a8287 dhcp: parse pad option as single byte
DHCP option 0 is a one-byte padding field, but it was parsed as a generic TLV.
This consumed the following option code as its length and could prevent later
options from being inspected.

Handle PAD explicitly so parsing resumes at the next option.

Ticket #8819

(cherry picked from commit a06e7c7422)
2 months ago
Juliana Fajardini c45d68ebde pgsql: bound tx.responses (configurable)
Since the PostgreSQL protocol doesn't impose any clear limits to how
many responses a backend could send, add one to the app-proto parser.

Using 21-64 as the accepted values, and 64 as the default:

The Start-up phase may have up to 17-18 ParameterStatus messages, plus
AuthOk, BackendKeyData and ReadyForQuery: 20, with extra room to be on
the safer side: 21

And 64 as upper limit, because as we currently summarize query
responses, we already don't get flooded by DataRow and Copy responses
messages, so we don't expect to see that many responses in a single
transaction for the pgsql, with the current implementation.

Ticket: #7263
(cherry picked from commit f839581dba)
2 months ago
Juliana Fajardini d38c2cc5e7 pgsql/logger: close json array if params truncated
Pgsql logger would only open a ParameterStatus message array and only
close it when a different type of message was seen (following an
expected pgsql transaction style). However, if no different type of
message followed the ParameterStatus message, the array remained open,
leading to an unbalanced `}` count, and poisoning the whole JSON log,
from that point on.

Now, if we finish the responses logging loop without reaching another
type of response, close the array, regardless.

Ticket: #9012
(cherry picked from commit 85168b8036)
2 months ago
Juliana Fajardini dd53a71ce2 pgsql: better boundaries to row_description/data_row
parse_row_description and parse_consolidated_data_row read a field_count
from the message body and use that to iterate a slice, without checking
whether the count actually fits the body.

A backend-controlled attack could lead to fewer fields logged, or
stalling of the parser to-client direction for the duration of the flow.

A malformed_response event is set for pgsql, if either of those
message's inner parsers has a field_count that can't be reconciled with
the body slice.

A new pgsql.response log field is added to indicate this, too:
pgsql.response.row_description_malformed, a boolean. This wasn't added
to the consolidated data row message, per its summarization nature.

The row_description unit test buffer declared a length one byte longer
than its three fields occupy. The old code silently discarded that
surplus byte; the new one reports it, so the buffer was corrected.

Ticket: #8885
(cherry picked from commit fe939e8da7)
2 months ago
Philippe Antoine a9594f8775 http: warn once for chunk extension
Avoids pushing multiple log messages, when the consumer will
only set one app-layer event for the tx

Ticket: 8867
(cherry picked from commit 72829dbaea)
2 months ago
Philippe Antoine 9267edf404 http: warn once for response 100-continue already seen
Avoids pushing multiple log messages, when the consumer will
only set one app-layer event for the tx
Also, this is a warning, not an error, as we continue parsing.

Ticket: 8867
(cherry picked from commit 4dd7ebf079)
2 months ago
Philippe Antoine b3fca065b5 http1: use strict brotli, forbid large window
Ticket: 9008

Avoids over-allocation from a few bytes

(cherry picked from commit fefe0a9b8b)
2 months ago
Philippe Antoine a005dbe846 http1: use brotli with owned BrotliState wrapper
Ticket: 9008

Will allow to use strict brotli, and forbid large window

(cherry picked from commit 2a85539ef0)
2 months ago
Philippe Antoine 8c79af57e6 http2: use strict brotli, forbid large window
Ticket: 9008

Avoids over-allocation from a few bytes

(cherry picked from commit 2b4d7a1f3d)
2 months ago
Philippe Antoine eac1c25a72 http2: use brotli with owned BrotliState wrapper
Ticket: 9008

Will allow to use strict brotli, and forbid large window

(cherry picked from commit a07cd82dc6)
2 months ago
Philippe Antoine ae2ebc21e0 ike: remove recursivity in functions
Ticket: 8800

Thus avoiding unbounded recursion

Before that, parse_payload could call
parse_security_association_payload which could call back
parse_payload if a type in the list was SecurityAssociation

But a Security Association only accepts the type Proposal in its
payload, see RFC 2408: section 3.5

There was another recursive path with parse_payload calling
parse_proposal_payload which called back parse_payload

And a Proposal only accepts the type Transform in its payload, see
RFC 2408: section 3.6

(cherry picked from commit b13c742a9c)
2 months ago
Juliana Fajardini b11da71b6a pgsql: fix regression in handling request gap
Fixes: 9aeeac53 ("pgsql: remove probe_ts function")

When the probe_ts function was removed in 9aeeac532, the request gap
handling got inverted, preventing re-sync of the app-proto from the
frontend side.

This could lead to detection evasion after a gap.

Ticket: #8822
(cherry picked from commit 7f4d44edc1)
2 months ago