Commit Graph

18356 Commits (b800ace56fb08c29aadb0f68a3bad1fe3e4a0d67)
 

Author SHA1 Message Date
Yash Datre b800ace56f detect: add tcp.session keyword for unified TCP lifecycle matching
Introduce the tcp.session: keyword that accepts a comma-separated subset
of {setup, established, closing} and matches packets whose TCP session
state falls within the named phases.

This lets a rule writer cover the full TCP lifecycle in one rule instead
of separate flow:not_established + flow:established rules.

Changes:
- New detect-tcp-session.{c,h} with parser, match function, unit tests
- Register DETECT_TCP_SESSION in detect-engine-register.{c,h}
- Add to Makefile.am source list
- Extend engine-analyzer text output for tcp.session:
- Extend firewall.json keyword_info with tcp_session phase values
- Update flow-keywords.rst documentation
- Require TCP protocol and SIG_FLAG_REQUIRE_PACKET at setup

Ticket: 7704
(cherry picked from commit 398687d5d4)
4 days ago
Yash Datre 353885acc2 detect: extend app-layer-protocol to accept a pipe-separated value list
Extend the app-layer-protocol keyword to accept a pipe-separated list of
protocol values, so a single rule can match any of several protocols:

    app-layer-protocol:[!]<proto1>|<proto2>[|...][,<qualifier>]...;

A non-negated list matches when the flow's protocol equals any listed value
(OR); a negated list matches when it equals none of them (NOR). The
single-value form and the trailing mode qualifier are unchanged.

Matching keeps the historical AppProtoEquals() equivalences by default
(dns/doh2, http/http1/http2, dcerpc/smb, ...). An `exact` qualifier selects
strict identity matching with no equivalences and no http umbrella; it
combines with a direction mode in any order. Because a flow is never the
generic ALPROTO_HTTP, `http,exact` is rejected at load.

Values are expanded once at rule load into an effective match-set bitmask, so
the per-packet match is a single bitmask test. Single-value rules remain
prefilterable; multi-value rules are excluded from prefiltering and an
explicit prefilter on them is rejected. Conflicting keyword combinations
(duplicate or overlapping negations, mixed positive/negated) are rejected at
load. Engine-analysis reports the effective match set.

Ticket: 7705
(cherry picked from commit 43bc2db41e)
4 days ago
Urval Kheni 8b0775f557 util: fix fallback memrchr() implementation
The fallback memrchr() implementation initialized the search pointer to
the one-past-end position and dereferenced it before decrementing, which
is undefined behavior in C.

Update the implementation to decrement the pointer before dereferencing
while preserving memrchr() semantics. Compare bytes using unsigned char
semantics to ensure values with the high bit set are handled correctly.

Refactor the fallback into a local SCMemrchrFallback() helper so it can
be exercised by unit tests on platforms that provide a native memrchr()
implementation.

Expand the unit test to cover first, middle, last, duplicate, single-byte,
zero-length, absent-element, and high-byte values.

Ticket: 9010

Signed-off-by: Urval Kheni <kheniurval777@gmail.com>
(cherry picked from commit b475cc25b6)
4 days ago
Jeff Lucovsky a2aa325f7f output/alert: tolerate a reference with no key
Substitute an empty string for a NULL key or reference in
AlertJsonReference() before the write, so the output no longer depends
on what a libc does with a null pointer and "%s", which the standard
leaves undefined. glibc prints "(null)"; nothing requires that.

Assert both are set alongside the substitution. DetectReferenceParse()
is the only producer of DetectReference and sets each string with its
length, so the assert cannot fire today -- it names the invariant for a
second producer that does not hold it, while the substitution covers a
release build, where DEBUG_VALIDATE_BUG_ON compiles out.

A release build that reaches the substitution logs whichever half it
has rather than crashing, and nothing records that it happened.

Issue: 8849
(cherry picked from commit 9cffa8ab49)
4 days ago
Jeff Lucovsky f111a51854 detect/reference: set key on the unknown-key path
Assign ref->key for a reference key that is not in reference.config, so
the fallback that registers a synthetic entry produces the same key and
key_len as an ordinary lookup. The assignment sat in the branch taken
when SCRConfGetReference() found the key; the fallback registered the
entry, looked it up again, and fell through with ref->key still at the
NULL SCCalloc() left.

AlertJsonReference() passed that key to snprintf() with "%s%s" and
sized the destination from key_len. With key NULL and key_len 0, a rule
carrying reference:unknownkey,001-2010 logged "(null)001-" on glibc,
and handed a null pointer to a "%s" conversion, which the standard
leaves undefined.

Invert the lookup test so the add-and-retry runs when the lookup fails
and both paths reach one assignment. The comment on that assignment
named REFERENCE_SYSTEM_NAME_MAX; the string copied is a URL, bound by
REFERENCE_CONTENT_NAME_MAX.

DetectReferenceParseTest03() loaded a rule with an unknown key and
checked only that the signature parsed, which it did throughout. Check
the resolved key, its length, and the reference value.

Issue: 8849
(cherry picked from commit 6216f9262c)
4 days ago
Jason Ish 27cb46c266 smtp: recover from rejected BDAT commands
A server can reject a BDAT command before the client sends the
advertised chunk. Suricata would keep waiting for those bytes and treat
the rest of the SMTP session as chunk data.

Keeps subsequent SMTP commands and message data in sync with the
server.

Ticket: 8995
(cherry picked from commit 51ac40009f)
4 days ago
Andreas Dolp ec3a9aa506 unix-socket: close socket and remove socket file on shutdown
Suricata never removed the unix command socket file after shutdown.
The socket path (sockettarget) is now preserved in the struct
UnixCommand_, because it is needed on shutdown to close the socket.

The cleanup is done in the shutdown path of UnixManager(), which is
reached uniformly whether shutdown is triggered by a fatal error or
a signal (e.g. SIGTERM) via THV_KILL. This also applies for a clean
shutdown via 'suricatasc -c shutdown'.

Ticket: 8799
(cherry picked from commit 011f52379c)
4 days ago
Philippe Antoine 6c204270db rfb: keep failure_reason as Vec<u8>
And log it with from_utf8_lossy

Since we may now cut a too big failure_reason breaking a valid
utf-8 string

Ticket: 8731
(cherry picked from commit c608165c04)
4 days ago
Philippe Antoine 51a6e69b4e rfb: limit strings length
Ticket: 8731

Adds a configurable limit to string lengths to avoid to retain
too much memory for too long, and avoid producing log events
that are too big

(cherry picked from commit f9515dc71d)
4 days ago
Philippe Antoine 7ee6f328aa rfb/jsonschema: add missing field
Ticket: 6478
(cherry picked from commit d0cc39c79a)
4 days ago
Lukas Sismis 4ca257b612 fw: document config action in FW mode
(cherry picked from commit 3f0d99d9c2)
4 days ago
Lukas Sismis 6370f599d4 fw: disallow config to be used as a default policy
Ticket: 8955
(cherry picked from commit 17e2e7f892)
4 days ago
Lukas Sismis 7b0fd8158b fw: allow pass as a secondary action only for accept
Previously, hook sequences in both rules and default policies
allowed `pass` to be combined with incompatible hooks (e.g.
reject or drop).

This commit clamps pass to accept only.

Ticket: 8955
(cherry picked from commit d6521adf4e)
4 days ago
Lukas Sismis 610ecdb725 fw: validate scope inheritance in policies and rules
A secondary action given without an explicit scope inherits the scope of
the primary action, but was never validated against the scopes it
supports itself. `pass` only supports packet and flow scope but
the inheritance was never verified.

Ticket: 8955
(cherry picked from commit 4bafe61ecf)
4 days ago
Lukas Sismis e59df8187f fw: respect configured policies in the rule analysis output
Some firewall rule analysis output had hardcoded paths.
This commit is querying respective tables and uses the actual
values.

Ticket: 8952
(cherry picked from commit 25ece1ed38)
4 days ago
Lukas Sismis 3d2171a317 logging: prevent double-free multi-threaded logging
When multithreaded output was enabled, all threads freed
shallow-copy of sensor and prefix names.

This commit adds a guard so that only the parent frees the
allocated buffers.

Ticket: 9018
(cherry picked from commit 7ca9471145)
4 days ago
Stephen Donnelly d5cb294d48 source/erf: Handle ERF META and PAD record types and extension headers
Add support for ERF record types META and PAD, plus additional ETH types.

Add support for ERF extension headers.

These types and extension headers were already supported by erf-source-dag.

Made source-erf-file and source-erf-dag more consistent.

Ticket: 8962

Fixed merge conflicts on backport

(cherry picked from commit 3d42f7cf63)
4 days ago
Stephen Donnelly b5e22f78b9 erf/file: Don't trust ERF wlen and rlen from input file
When reading an ERF file do not trust the ERF header values.

Do not use wlen to set packet length.

Ticket: 8836

Read rlen bytes into MAX_PAYLOAD_SIZE buffer.
Use PacketCopyData() to safely update p.

Ticket: 8865
(cherry picked from commit c6dd80f787)
4 days ago
Victor Julien c80c803cb5 github-ci: remove Debian 11 build; Debian 11 is EOL
(cherry picked from commit 8e4d49df0d)
5 days ago
Victor Julien d201942911 ssl: fix SSLv2 CLIENT_HELLO underflow
SSLv2Decode() consumed six fixed CLIENT_HELLO body bytes (version +
cipher_spec_length + session_id_length) guarded only by input_len >= 6,
which checks the buffer remainder but not the record itself.  When an
attacker sends a record whose declared record_length is < 7 (e.g. 1),
bytes_processed advances past record_lengths_length + record_length,
leading an integer underflow.

Address by adding a record_length >= 7 check to the CLIENT_HELLO case.

Also add another check: bail if bytes_processed > record_length +
record_lengths_length.

Ticket: #8853.
(cherry picked from commit 928ac01215)
5 days ago
Victor Julien 5f61a8a4b7 tls: JA3 buffer pointers on allocation failure
Improper pointer handling would leave dangling pointers after allocation
failure that could get freed again (double free).

Ticket: #8857.
(cherry picked from commit 201ecd5618)
5 days ago
Jason Ish 0f3be94b06 psl: update to 2.1.228
Ticket: 8688
7 days ago
Victor Julien 1bcfc219f1 nfs: fix SECINFO_NO_NAME parser handling
nfs4_res_secinfo_no_name() used a local var "i2" to walk through
the security-flavor array entries, but returned the pre-walk var "i"
in the Ok at the end. Every byte of the flavor array was therefore left
unconsumed in the input stream and re-interpreted by count next iteration
as a subsequent compound operation.

Addressed by returning i2 instead of i so all flavor bytes are consumed.

Ticket: #8860.
(cherry picked from commit 9b491a131e)
1 week ago
Philippe Antoine 19698065ec http2: log :authority header as hostname
Ticket: 8774
(cherry picked from commit 0b0606b126)
1 week ago
Philippe Antoine bae703386b http2: use host header for http.host keyword
if :authority header is absent

Ticket: 8774
(cherry picked from commit f5e44ced1e)
1 week ago
Lukas Sismis d8cd5224c8 doc: update Rust installation instructions
Rust website has changed the location of the installer.
Additionally their installer now includes automatic append to
.bashrc to source the correct path to Rust binaries.

Cbindgen as an instruction is also removed as it is not needed
when building from the downloaded and packaged Suricata.

Ticket: 8344
(cherry picked from commit d7bf52e71c)
1 week ago
Philippe Antoine 82c4302a27 http2: host normalization handles ipv6 address
And does not consider automatically a port after first colon

Ticket: 8778
(cherry picked from commit b0b353d0c0)
1 week ago
Philippe Antoine 9d5230eff0 http2: code cleanup for http2_normalize_host
Just separate the steps in parsing, and deduplicate code

(cherry picked from commit 52c01543c9)
1 week ago
Jeff Lucovsky 14eb3d3521 suricata: bound stack trace formatting in signal handler
The crash handler built its stack trace by advancing a pointer with
the snprintf return value. That value is the length the output would
have had, not what was written, so once the trace filled msg the
pointer moved past the end of the buffer. Every size argument after
that, SC_LOG_MAX_LOG_MSG_LEN - (temp - msg), was negative and
converted to a huge size_t, and snprintf went on writing into the
stack past msg. With a deep enough stack the handler faults before it
can log the crash it exists to report.

The frame name lookup also compared unw_get_proc_name() against
UNW_ENOMEM, but libunwind returns the negated code, so the test
never fired. A lookup that failed with UNW_ENOINFO fell through
to the success branch and printed the name buffer, which
libunwind had not written.

Track space used with offset and use that on each snprintf call. Advance
by MIN(cw, remaining - 1) to prevent overruns.  The loop stops when
the buffer is full and closes the trace with "..." so a clipped message
is not read as a whole stack.

Failed symbol lookups now print "[unknown]:". -UNW_ENOMEM is not one of
them, since libunwind returns a truncated but usable name with it.
name starts as "?" so nothing is printed from it either way.

Ticket: 8846
(cherry picked from commit cd7f7751d5)
1 week ago
Jeff Lucovsky d22b91c451 doc/bytemath: document the result of wide shifts
Record beside the existing note about division by zero that << and >>
give 0 when rvalue is 64 or more, that a rule giving such an rvalue as
a number still loads with a warning, and that --strict-rule-keywords
makes it fail to load instead. rvalue can name a byte_extract or
byte_math variable rather than a number, and then the count is not
known until the rule runs, so the rule text does not say whether it
will reach 64.

The note on main stops at the result, because 89d09c457c rejects such
a rule there instead of warning about it.

Issue: 8845
Issue: 8902
(cherry picked from commit 4a647784c7)
2 weeks ago
Jeff Lucovsky a400229a1c detect/bytemath: warn on literal shift counts of 64
Warn from DetectByteMathSetup() when byte_math pairs << or >> with a
literal rvalue of 64 or more, naming the signature by sid. Such a
shift gives 0 for every packet: DetectByteMathDoMatch() zeroes the
result once the count reaches 64, the width of the uint64_t being
shifted. rvalue was bounded only to the u32 range, so the rule loaded
and ran a shift whose result was 0 whatever the packet held.

The rule still loads. main rejects it in 89d09c457c, the commit this
one is derived from, but a released branch should not stop loading
rules that loaded before. Passing byte_math to --strict-rule-keywords
turns the warning into a load failure, the same escalation classtype
and reference apply to values they cannot check.

A variable rvalue draws no warning. It resolves to a preceding
byte_extract or byte_math result, whose value is known only once the
rule runs, so the guard in DetectByteMathDoMatch() stays the only
check on that path.

Issue: 8845
Issue: 8902
(cherry picked from commit 89d09c457c)
2 weeks ago
Jeff Lucovsky 2a06dcba00 detect/bytemath: guard right shift against wide counts
Zero the result when a byte_math right shift count reaches 64, the
width of the uint64_t being shifted, so the operation no longer
depends on behavior C11 6.5.7p3 leaves undefined. The left shift case
has done this since 473ca6dcf4; the right shift case was left
unguarded.

DetectByteMathDoMatch() shifted by whatever count it was handed. On
x86_64 the hardware masks the count to its low six bits, so a count of
64 became a shift of 0 and returned the extracted value unchanged
instead of 0. That value is stored in det_ctx->byte_values[] and feeds
any byte_test, isdataat, or content offset later in the signature, so
the signature's verdict follows from an arithmetic result the standard
does not define.

The count reaches the shift from the wire. When byte_math names a
variable for rvalue, DetectEngineContentInspectionInternal() reads it
out of det_ctx->byte_values[] at
detect-engine-content-inspection.c:614, where a preceding byte_extract
stored bytes taken from the payload, so one payload byte of 0x40 sets
the count to 64.

Issue: 8845
Issue: 8902
(cherry picked from commit e5d035fd16)
2 weeks ago
Victor Julien c5e7b77eeb affinity: handle NULL set name from --set affinity path
Setting a cpu-affinity path with --set, like

  --set threading.cpu-affinity.worker-cpu-set.threads=28

creates an intermediate node under cpu-affinity whose val is NULL.

With a legacy list format cpu-affinity, AffinitySetupLoadFromConfig()
red the set name from the node val and passed it to
GetAffinitySetName(), which then dereferenced the NULL pointer.

Address it by simply checking for the NULL.

Ticket: #6735.
(cherry picked from commit 54504ed13c)
2 weeks ago
Shivani Bhardwaj 53fd78a060 flow/rate: fix ring flushing
The fn to flush the ring is supposed to flush the entire ring buffer but
it only resets the buffer up to the "length" bytes. Fix this calculation
to correctly reflect the number of bytes that need to be reset.

Ticket: 8826
(cherry picked from commit 389700eca2)
2 weeks ago
Denis Balashov 3b04b76731 util/file: add unit test for inspect window overflow
Ticket: 8678

With an inspect window of 0xAAAAAAAB the `window * 3` guard wrapped to 1
in uint32_t arithmetic, so it passed for a 64 byte file and
content_inspected was set to `file->size - window`, an underflow.

(cherry picked from commit 8e551f2860)
2 weeks ago
Denis Balashov c4b5f8d418 util/file: fix integer overflow in inspect window comparison
Ticket: 8678

In FilePruneFile() `window * 3` was computed in uint32_t arithmetic.
The guard exists to ensure `file->size > window`, so on wrap around
`file->size - window` underflows and content_inspected is set to a
bogus value, breaking file inspection.

Make window uint64_t so the multiplication cannot wrap.

(cherry picked from commit f3910d557d)
2 weeks ago
Lukas Sismis c6ba237448 firewall: validate action scope against the hook class
Validate the resolved scope against the class of hook it is being applied
to and fail at startup if it does not fit.

Ticket: 8770
(cherry picked from commit 092ae272e2)
2 weeks ago
Lukas Sismis efc82a67cb firewall: add default-policy to policy config
Every hook has a built-in default policy, but expressing anything other
than the built-in meant naming each hook explicitly.
This commit adds a `default-policy` setting that covers all hooks below it.
For any hook the most specific setting present wins.

Ticket: 8770
(cherry picked from commit 0aaa80d4f3)
2 weeks ago
Lukas Sismis 400e750496 firewall: share the generic app hook name helper
Mapping an app-layer progress state to its generic request-/response-
hook alias was hardcoded in multiple places.

This commit adds a wrapper to unify it to a single function.
It returns the config-form (hyphenated) name, or NULL for an
intermediate state.

Ticket: 8770
(cherry picked from commit 1aa0259876)
2 weeks ago
Jason Ish c3134d4ab8 github-ci: update fedora 42 builds to fedora 44
Fedora 42 is EOL.
2 weeks ago
Victor Julien 4b3ad70aec fuzz: use heap threadvars allocations
Use new allocator to properly set up thread storage.

(cherry picked from commit 9e82ff82e2)
2 weeks ago
Victor Julien 8b665b1e63 detect/threshold: don't double init per thread cache
Can get called multiple times in the multi-tenancy case.

(cherry picked from commit cefee1390e)
2 weeks ago
Victor Julien b72d0df5a9 detect/threshold: fix unittests for storage based cache
(cherry picked from commit f67dadc3d8)
2 weeks ago
Victor Julien 1794222100 threshold: use seed consistently in hashing
Use for IPv6 in the main hash.

Update IPv4 thread cache to also use a seed. For this the thread
initialization is done at thread init instead on the first packet. The
thread ctx is no longer stored in a thread_local, but instead uses the
thread storage API to store in the ThreadVars. This way it will stay
active during rule reloads as well.

Ticket: #8617.
(cherry picked from commit c27868a8c5)
2 weeks ago
Victor Julien 03c5358108 hash: allow registing with a seed value
Seed value will have to be used by the caller's hash function.

(cherry picked from commit b742d58544)
2 weeks ago
Victor Julien 4a3c4286fe threads: use threadvars memory helpers
(cherry picked from commit 730ff5075d)
2 weeks ago
Victor Julien 6a684e2ff5 threads: add threadvars allocator and free func
Mostly meant to help unittests and fuzz targets alloc the storage
correctly.

(cherry picked from commit ad1459df72)
2 weeks ago
Jason Ish 098022aee5 github-ci: set rust version known to 1.98.0
The previous commit makes us clippy clean on 1.98.0.
2 weeks ago
Jason Ish a9d5487cd2 rust: fix clippy warnings
Fix the following lints:
- clippy::box_default
- clippy::byte_char_slices
- clippy::collapsible_match
- clippy::manual_clear
- clippy::question_mark
- clippy::to_string_in_format_args
- clippy::useless_borrows_in_formatting
- unused_imports (rustc)
2 weeks ago
Philippe Antoine 6f4172b58b datasets: add size checks for hashes read
Ticket: 8768
(cherry picked from commit 7c394b9774)
2 weeks ago