Issue:
https://redmine.openinfosecfoundation.org/issues/2041
One approach to fixing this issue to just validate the
checksum instead of regenerating it and comparing it. This
method is used in some kernels and other network tools.
When validating, the current checksum is passed in as an
initial argument which will cause the final checksum to be 0
if OK. If generating a checksum, 0 is passed and the result
is the generated checksum.
When detection is running flags are set on flows to indicate if file
hashing is needed. This is based on global output settings and rules.
In the case of --disable-detection this was not happening, so all
files where hashed with all methods. This has a significant
performance impact.
This patch adds logic to set the flow flags in --disable-detect mode.
When bytejump was told to convert some payload data to int from a
string it would print an error to the screen if the conversion
failed. This is unwanted as the payload is controlled by an attacker
and printing is expensive.
A GAP during protocol detection would lead to all reassembly
getting disabled, so also the raw reassembly. In addition, it
could prevent the opposing side from doing protocol detection.
This patch remove the 'disable reassembly' logic. Stream engine
will take the stream with GAP and app-layer will make the proto
detection as complete.
All loggers were wrapping just the write in a lock with some
updating a counter. This moves the lock into the write function.
The log_ctx alerts counter was also removed as many modules have
stopped using this and the alert count is available elsewhere.
Should satisfy Coverity CID 1400798:
CID 1400798 (#1 of 1): Data race condition (MISSING_LOCK) 2.
missing_lock: Accessing log_ctx->rotation_flag without holding lock
LogFileCtx_.fp_mutex. Elsewhere, "LogFileCtx_.rotation_flag" is accessed
with LogFileCtx_.fp_mutex held 4 out of 5 times.
Which appears to be a false positive as all calls to SCLogFileWrite
were done under lock, but this will make it more explicit.
Match on TLS certificate serial number using tls_cert_serial
keyword, e.g.:
alert tls any any -> any any (msg:"TLS cert serial test";
tls_cert_serial; content:"5C:19:B7:B1:32:3B:1C:A1";
sid:12345;)
Add function LuaGetCertSerial to print serial number from TLS
certificate.
Example:
function log (args)
serial = TlsGetCertSerial()
if serial then
file:write(serial .. "\n");
file:flush()
end
end
Give unified2 a nostamp option which will create the file
without the timestamp suffix (like Snort's nostamp option).
Also register for rotation notification on SIGHUP so the file
will be recreated if it is removed by an external rotation
program (only when nostamp is used).
Log src_ip, dst_ip and proto for root packet (p->root) if the
packet that triggered is inside a tunnel, as JSON object
'tunnel'. Also log recursion depth to indicate the depth of
the tunnel.
Move code to get 5-tuple in JSON object to own function 'JsonFiveTuple'.
This enables this code to be reused when printing 'parent' JSON object in
output-json-alert.
add-hostbit adds a named hostbit with an expire time in seconds.
remove-hostbit removes hostbit by name.
add-hostbit, remove-hostbit return success or failure.
list-hostbit returns a json array of hostbits with their name and
expire time:
{
"message": {
"count": 1,
"hostbits":
[{
"expire": 3222,
"name": "firefox-users"
}]
},
"return": "OK"
}
Until now the way to specify a var name in pcre substring capture
into pkt and flow vars was to use the pcre named substring support:
e.g. /(?P<pkt_somename>.*)/
This had 2 drawbacks:
1. limitations of the name. The name could be max 32 chars, only have
alphanumeric and the underscore characters. This imposed limitations
that are not present in flowbits/ints.
2. we didn't actually use the named substrings in pcre through the
API. We parsed the names separately. So putting the names in pcre
would actually be wasteful.
This patch introduces a new way of mapping captures with names:
pcre:"/(.*)/, pkt:somename";
pcre:"/([A-z]+) ([0-9]+)/, pkt:somename,flow:anothername";
The order of the captures and the order of the names are mapped 1 on 1.
This method is no longer limited by the pcre API's naming limits. The
'flow:' and 'pkt:' prefixes indicate what the type of variable is. It's
mandatory to specify one.
The old method is still supported as well.
Flowvars were already using a temporary store in the detect thread
ctx.
Use the same facility for pktvars. The reasons are:
1. packet is not always available, e.g. when running pcre on http
buffers.
2. setting of vars should be done post match. Until now it was also
possible that it is done on a partial match.
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
Matches on the start of a HTTP request or response.
Uses a buffer constructed from the request line and normalized request
headers, including the Cookie header.
Or for the response side, it uses the response line plus the
normalized response headers, including the Set-Cookie header.
Both buffers are terminated by an extra \r\n.
A sticky buffer that allows content inspection on a contructed buffer
of HTTP header names. The buffer starts with \r\n, the names are
separated by \r\n and the end of the buffer contains an extra \r\n.
E.g. \r\nHost\r\nUser-Agent\r\n\r\n
The leading \r\n is to make sure one can match on a full name in all
cases.
Some keywords need a scratch space where they can do store the results
of expensive operations that remain valid for the time of a packets
journey through the detection engine.
An example is the reconstructed 'http_header' field, that is needed
in MPM, and then for each rule that manually inspects it. Storing this
data in the flow is a waste, and reconstructing multiple times on
demand as well.
This API allows for registering a keyword with an init and free function.
It it mean to be used an initialization time, when the keyword is
registered.
To replace the hardcoded SigMatch list id's, use this API to register
and query lists by name.
Also allow for registering descriptions and whether mpm is supported.
Registration is only allowed at startup.
For lists that are registered multiple times, like http_header and
http_cookie, making the engines owner of the lists is complicated.
Multiple engines in a sig may be pointing to the same list. To
address this the 'free' code needs to be extra careful about not
double freeing, so it takes an approach to first fill an array
of the to-free pointers before freeing them.
A high level proto like HTTP implies TCP. However this wasn't set
until after all the parsing was complete which means that keywords
couldn't test if the ipproto matched.
This patch populates the ipprotos right when the higher level proto
is parsed.
The IP protocol was not being used to match fragments with
their packets allowing a carefully constructed packet
with a different protocol to be matched, allowing re-assembly
to complete, creating a packet that would not be re-assembled
by the destination host.
Due to the use of AFL_LOOP and initialization/deinit outside of it,
part of the fuzzing relied on the global 'state' in flow and defrag.
Because of this crashes that were found could not be reproduced. The
saved crash input was only the last in the series.
This patch addresses that. It requires a new output directory 'dump'
where the packet fuzzers will store all their input. If the AFL_LOOP
fails the files will not be removed and this 'serie' can be read
again for reproducing the issue.
e.g.: AFL would work with:
--afl-decoder-ppp=@@
and after a crash is found the produced serie can be read with:
--afl-decoder-ppp-serie=1486656919-514163
The series have a timestamp as name and a suffix that controls the
order in which the files will be 'replayed' in Suricata.
The size of a memory buffer to be allocated was kept in a signed int
instead of a size_t, leading to an overflow when large lists of long
and diverse patterns cause the amount of AC states to blow up (>2GB).
Fixes Redmine issues #1827 and #1843.
Signed-off-by: Sascha Steinbiss <sascha@steinbiss.name>
The `ts_ecr' and `ts_val' struct fields are integer types, not
pointers. This leads GCC 6.3.0 to complain about comparisons to
NULL.
Signed-off-by: Sascha Steinbiss <sascha@steinbiss.name>
The code to get the rule group (sgh) would return the group for
IP proto 0 instead of nothing. This lead to certain types of rules
unintentionally matching (False Positive).
Since the packets weren't actually IP, the logged alert records
were missing the IP header.
Bug #2017.
When packet is coming from a real ethernet card, the kernel is
stripping the vlan header and delivering a modified packet so
we need to insert the VLAN header back before sending the packet
on the wire.
To do so, we pass an option to the raw socket to add a reserve
before the packet data. It will get Suricata some head room to
to move the ethernet addresses before there actual place and
and insert the VLAN header in the correct place.
We get VLAN info from the ring buffer as the call of AFPWrite is
always done in the release function so we still have access to the
memory.
The JSON logger had already been updated to handle
transactions without a response. Apply the same logic
to the older dns-log where a logger is registered
for each direction.
Fixes issue 2012.
If the app-layer-parsing has a very long content it exceeds the maximum
defined in "alproto_name". This adds a check for the too long content
before it will be passed to "strlcpy" and logs an error.
The new Hyperscan 4.4 API provides a function to check for SSSE3
presence at runtime. This allows us to fall back to non-Hyperscan
matchers on systems without SSSE3 even when the suricata executable
is built with Hyperscan support. Addresses Redmine issue #2010.
Signed-off-by: Sascha Steinbiss <sascha@steinbiss.name>
Tested-by: Arturo Borrero Gonzalez <arturo@debian.org>
If segments section in the yaml is ommitted (default) or when the
pool size is set to 'from_mtu', the size of the pool will be MTU
minus 40. If the MTU couldn't be determined, it's assumed to be
1500, so the segment size for the bool will be 1460.
At shutdown, all flows that still need work are handled by the flow
force reassembly logic. This means one or more flow end pseudo packets
are generated and pushed through the engine for final detection and
logging.
In some cases this would not work correctly. This was caused by the
flow timeout logic kicking in before all the 'live' packets were
processed. Before the flow timeout handling runs the receive threads
are disabled, however the engine did not wait for the in-flight
packets to be fully processed. In autofp mode, packets could still
be in the queue between receive thread(s) and flow worker(s).
This patch adds a new function that 'drains' all the packet threads
of any in-progress packets before moving on the flow timeout logic.
Bug #1946.
Add SCFlowHasAlerts() to check if a flow has alerts. Returns true
on alerts, false otherwise.
Example:
has_alerts = SCFlowHasAlerts()
if has_alerts then
-- do something
end
This patch introduces the FileDataSize and FileTrackedSize functions.
The first one is just a renaming of the initial FilSize function
whereas the other one is using the newly introduced size field as
value.
The file size returned by FileSize is invalid if file store is not
used so we introduce a new size field in File structure that is used
to store the size.
Code was failing on a NULL return value which can be returned
when there was nothing todo instead of an error. Instead
check the errbuf for a non-NULL value to determine error.
Prevents the case where the logged id is incremented if a newer
transaction is complete and an older one is still outstanding.
For example, dns request0, unsolicited dns response, dns response0
would result in the valid response0 never being logged.
Similarily this could happen for:
request0, request1, response1, response0
which would end up having request0, request1 and response1 logged,
but response0 would not be logged.
This patch fixes an issue with hash computation resulting in the
invalidity of at least one hash when at least two different hashes
functions were used.
Impact was setting as `force-hash: [md5, sha256]` not to be valid.
Also it could lead to false negative if too different hash functions
had to be used on a single file due to signatures.
Fix bug that causes Suricata to crash when the tls.store keyword is used.
*** Error in `/usr/bin/suricata': free(): invalid next size (fast):
0x00007fd4b4373180 ***
null: At condition templatejs != NULL, the value of templatejs must be
NULL.
dead_error_condition: The condition templatejs != NULL cannot be true.
113 if (templatejs != NULL) {
CID 1324964 (#1 of 1): Logically dead code (DEADCODE)
dead_error_line: Execution cannot reach this statement:
json_decref(templatejs);.
114 json_decref(templatejs);
115 }
CID 1374306 (#1 of 1): Dereference before null check (REVERSE_INULL)
check_after_deref: Null-checking dns_state suggests that it may be null,
but it has already been dereferenced on all paths leading to the check.
585 if (dns_state != NULL && f != NULL) {
586 dns_state->last_req = f->lastts;
587 }
CID 1374305 (#1 of 1): Dereference before null check (REVERSE_INULL)
check_after_deref: Null-checking dns_state suggests that it may be null,
but it has already been dereferenced on all paths leading to the check.
366 if (dns_state != NULL && f != NULL) {
367 dns_state->last_req = f->lastts;
368 }
CID 1374307 (#1 of 1): Dereference before null check (REVERSE_INULL)
check_after_deref: Null-checking dns_state suggests that it may be null,
but it has already been dereferenced on all paths leading to the check.
317 if (dns_state != NULL && f != NULL) {
318 dns_state->last_resp = f->lastts;
319 }
Regular expression was not matching some authorized setting like
"![1234, 1235]". This patch simplify the regexp to match on
possible character and let the port parsing code handle the
complete verification.
When BUG_ON is a wrapper for assert(), we risk getting rid of certain
code lines. Assert is a no-op when NDEBUG is defined.
This patch defines an alternate path for BUG_ON that exits after
printing an error.
Bug #2003.
There have been some ICMPv6 types missing within the DecodeICMPV6 that
are added by this commit and the code check is adjusted to always use
the DEFINE.
When registering a probing parser allow to_server and
to_client parsers to be registered. Previously the
probing parser may be called for both directions which
in some cases works OK, but in others can cause
the to_client side to be detected as failed.
RFC states that "Commands and replies are not case sensitive" and
patterns were registered to be case sensitive. So this patch fixes
a trivial evasion of SMTP signatures.
Tls packets may contain several records. This increase the number
of allowed records per packet from 30 to 255, and adds a new and
more informative decoder event when this limit is reached.
No extensions are allowed in <TLSv.1.2, so don't trigger SURICATA
TLS handshake invalid length decoder event when no extensions are
specified in CLIENT HELLO.