Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/userguide/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ Major changes
content that matched just because it fell in the inspection chunk without wholly
belonging to any one request/response may not match any longer.

- If a byte keyword (such as ``byte_extract`` or ``byte_math``, etc) is used with
a variable, and that variable usage is with a buffer other than the one used
to create the variable, a warning is printed and the rule is loaded. The
command-line option ``--strict-rule-keywords`` should be used to produce
an error message and prevent the rule from loading. See
https://redmine.openinfosecfoundation.org/issues/1412 for more information.

Removals
~~~~~~~~
- The ssh keywords ``ssh.protoversion`` and ``ssh.softwareversion`` have been removed.
Expand Down
34 changes: 20 additions & 14 deletions src/detect-byte-extract.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "detect.h"
#include "detect-engine.h"
#include "detect-byte.h"
#include "detect-content.h"
#include "detect-pcre.h"
#include "detect-bytejump.h"
Expand Down Expand Up @@ -364,6 +365,15 @@ static void DetectByteExtractFree(DetectEngineCtx *de_ctx, void *ptr)
SCByteExtractFree(ptr);
}

static inline bool DetectByteExtractSMNameMatch(const SigMatch *sm, const char *arg)
{
if (sm->type == DETECT_BYTE_EXTRACT) {
const SCDetectByteExtractData *bed = (const SCDetectByteExtractData *)sm->ctx;
return strcmp(bed->name, arg) == 0;
}
return false;
}

/**
* \brief Lookup the SigMatch for a named byte_extract variable.
*
Expand All @@ -372,30 +382,26 @@ static void DetectByteExtractFree(DetectEngineCtx *de_ctx, void *ptr)
*
* \retval A pointer to the SigMatch if found, otherwise NULL.
*/
SigMatch *DetectByteExtractRetrieveSMVar(const char *arg, int sm_list, const Signature *s)
const SigMatch *DetectByteExtractRetrieveSMVar(
const char *arg, int sm_list, int *found_list, const Signature *s)
{
for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
SigMatch *sm = s->init_data->buffers[x].head;
const SigMatch *sm = s->init_data->buffers[x].head;
while (sm != NULL) {
if (sm->type == DETECT_BYTE_EXTRACT) {
const SCDetectByteExtractData *bed = (const SCDetectByteExtractData *)sm->ctx;
if (strcmp(bed->name, arg) == 0) {
return sm;
}
if (DetectByteExtractSMNameMatch(sm, arg)) {
*found_list = s->init_data->buffers[x].id;
return sm;
}
sm = sm->next;
}
}

for (int list = 0; list < DETECT_SM_LIST_MAX; list++) {
SigMatch *sm = s->init_data->smlists[list];
const SigMatch *sm = s->init_data->smlists[list];
while (sm != NULL) {
// Make sure that the linked buffers ore on the same list
if (sm->type == DETECT_BYTE_EXTRACT && (sm_list == -1 || sm_list == list)) {
const SCDetectByteExtractData *bed = (const SCDetectByteExtractData *)sm->ctx;
if (strcmp(bed->name, arg) == 0) {
return sm;
}
if (DetectByteExtractSMNameMatch(sm, arg)) {
*found_list = list;
return sm;
}
sm = sm->next;
}
Expand Down
3 changes: 2 additions & 1 deletion src/detect-byte-extract.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@

void DetectByteExtractRegister(void);

SigMatch *DetectByteExtractRetrieveSMVar(const char *, int sm_list, const Signature *);
const SigMatch *DetectByteExtractRetrieveSMVar(
const char *, int sm_list, int *found_list, const Signature *);
int DetectByteExtractDoMatch(DetectEngineThreadCtx *, const SigMatchData *, const Signature *,
const uint8_t *, uint32_t, uint64_t *, uint8_t);

Expand Down
24 changes: 17 additions & 7 deletions src/detect-byte.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2020 Open Information Security Foundation
/* Copyright (C) 2020-2025 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand Down Expand Up @@ -32,25 +32,35 @@
*
* \param arg The name of the variable being sought
* \param s The signature to check for the variable
* \param strict Match if and only iff the list sought and the list found equal.
* \param sm_list The caller's matching buffer
* \param index When found, the value of the slot within the byte vars
*
* \retval true A match for the variable was found.
* \retval false
*/
bool DetectByteRetrieveSMVar(
const char *arg, const Signature *s, int sm_list, DetectByteIndexType *index)
bool DetectByteRetrieveSMVar(const char *arg, const Signature *s, bool strict, int sm_list,
DetectByteIndexType *index, int rule_line)
{
SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(arg, sm_list, s);
bool any = sm_list == -1;
int found_list;
const SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(arg, sm_list, &found_list, s);
if (bed_sm != NULL) {
if (DetectByteListMismatch(any, sm_list, found_list, strict, arg, rule_line)) {
return false;
}

*index = ((SCDetectByteExtractData *)bed_sm->ctx)->local_id;
return true;
}

SigMatch *bmd_sm = DetectByteMathRetrieveSMVar(arg, sm_list, s);
const SigMatch *bmd_sm = DetectByteMathRetrieveSMVar(arg, sm_list, &found_list, s);
if (bmd_sm != NULL) {
*index = ((DetectByteMathData *)bmd_sm->ctx)->local_id;
return true;
if (!DetectByteListMismatch(any, sm_list, found_list, strict, arg, rule_line)) {
*index = ((DetectByteMathData *)bmd_sm->ctx)->local_id;
return true;
}
}

return false;
}
20 changes: 19 additions & 1 deletion src/detect-byte.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,24 @@

typedef uint8_t DetectByteIndexType;

bool DetectByteRetrieveSMVar(const char *, const Signature *, int sm_list, DetectByteIndexType *);
bool DetectByteRetrieveSMVar(const char *, const Signature *, bool strict, int sm_list,
DetectByteIndexType *, int rule_line);

// Once a variable is found, apply strict semantics (error) else warning
static inline bool DetectByteListMismatch(
bool any, int sm_list, int found_list, bool strict, const char *arg, int rule_line)
{
if (any || sm_list == found_list)
return false;

if (strict) {
return true;
}

SCLogWarning("Using byte variable from a different buffer may produce indeterminate "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move this check into a validate callback so that the sid is available in a warning?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that Philippe's comment here also make sense: https://github.com/OISF/suricata/pull/13564/files/664e61a2678b90d25e3f27937059a2f4817aaece#r2183567368

(apologies for the very late reply)

"results; variable: \"%s\" at line %" PRId32 "",
arg, rule_line);
return false;
}

#endif /* SURICATA_DETECT_BYTE_H */
6 changes: 4 additions & 2 deletions src/detect-bytejump.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,8 @@ static int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, const char

if (nbytes != NULL) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(nbytes, s, sm_list, &index)) {
if (!DetectByteRetrieveSMVar(nbytes, s, SigMatchStrictEnabled(DETECT_BYTEJUMP), sm_list,
&index, de_ctx->rule_line)) {
SCLogError("Unknown byte_extract var "
"seen in byte_jump - %s",
nbytes);
Expand All @@ -557,7 +558,8 @@ static int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, const char

if (offset != NULL) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(offset, s, sm_list, &index)) {
if (!DetectByteRetrieveSMVar(offset, s, SigMatchStrictEnabled(DETECT_BYTEJUMP), sm_list,
&index, de_ctx->rule_line)) {
SCLogError("Unknown byte_extract var "
"seen in byte_jump - %s",
offset);
Expand Down
43 changes: 25 additions & 18 deletions src/detect-bytemath.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,8 @@ static int DetectByteMathSetup(DetectEngineCtx *de_ctx, Signature *s, const char

if (nbytes != NULL) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(nbytes, s, sm_list, &index)) {
if (!DetectByteRetrieveSMVar(nbytes, s, SigMatchStrictEnabled(DETECT_BYTEMATH), sm_list,
&index, de_ctx->rule_line)) {
SCLogError("unknown byte_ keyword var seen in byte_math - %s", nbytes);
goto error;
}
Expand All @@ -370,7 +371,8 @@ static int DetectByteMathSetup(DetectEngineCtx *de_ctx, Signature *s, const char

if (rvalue != NULL) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(rvalue, s, sm_list, &index)) {
if (!DetectByteRetrieveSMVar(rvalue, s, SigMatchStrictEnabled(DETECT_BYTEMATH), sm_list,
&index, de_ctx->rule_line)) {
SCLogError("unknown byte_ keyword var seen in byte_math - %s", rvalue);
goto error;
}
Expand Down Expand Up @@ -432,6 +434,15 @@ static void DetectByteMathFree(DetectEngineCtx *de_ctx, void *ptr)
SCByteMathFree(ptr);
}

static inline bool DetectByteMathSMNameMatch(const SigMatch *sm, const char *arg)
{
if (sm->type == DETECT_BYTEMATH) {
const DetectByteMathData *bmd = (const DetectByteMathData *)sm->ctx;
return strcmp(bmd->result, arg) == 0;
}
return false;
}

/**
* \brief Lookup the SigMatch for a named byte_math variable.
*
Expand All @@ -440,32 +451,28 @@ static void DetectByteMathFree(DetectEngineCtx *de_ctx, void *ptr)
*
* \retval A pointer to the SigMatch if found, otherwise NULL.
*/
SigMatch *DetectByteMathRetrieveSMVar(const char *arg, int sm_list, const Signature *s)
const SigMatch *DetectByteMathRetrieveSMVar(
const char *arg, int sm_list, int *found_list, const Signature *s)
{
for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
SigMatch *sm = s->init_data->buffers[x].head;
const SigMatch *sm = s->init_data->buffers[x].head;
while (sm != NULL) {
if (sm->type == DETECT_BYTEMATH) {
const DetectByteMathData *bmd = (const DetectByteMathData *)sm->ctx;
if (strcmp(bmd->result, arg) == 0) {
SCLogDebug("Retrieved SM for \"%s\"", arg);
return sm;
}
if (DetectByteMathSMNameMatch(sm, arg)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still #13564 (comment)

This change looks suspicious

Did you test a rule with 2 buffers, each buffer doing a byte_extract+ byte_math ?

I am afraid that with this change, the second buffer will get their found_list from the first buffer when it uses to get the right sm_list == list in current code

Do you have a test for it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule is handled correctly -- is this what you were thinking?

alert ip any any -> any any (msg:"multi buffer"; ipv4.hdr;byte_extract:1,0,header; byte_test:1,!=,header,1;tcp.hdr; byte_extract:1,0,header2, relative;byte_test:1,=,header2,1;sid: 1;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok... I will test it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, buffers are ok because they run only the first loop of `DetectByteExtractRetrieveSMVar``

The second loop (where you removed the check list==sm_list) is run for DETECT_SM_LIST_PMATCH and DETECT_SM_LIST_BASE64_DATA

So, this allows signature like
alert http any any -> any any (msg:"multi buffer2"; content: "toto"; byte_extract:1,0,header; http.user_agent; base64_decode; base64_data;byte_test:1,=,header,1;sid: 2;) to be accepted when it should not

SCLogDebug("Retrieved SM for \"%s\"", arg);
*found_list = s->init_data->buffers[x].id;
return sm;
}
sm = sm->next;
}
}

for (int list = 0; list < DETECT_SM_LIST_MAX; list++) {
SigMatch *sm = s->init_data->smlists[list];
const SigMatch *sm = s->init_data->smlists[list];
while (sm != NULL) {
// Make sure that the linked buffers ore on the same list
if (sm->type == DETECT_BYTEMATH && (sm_list == -1 || sm_list == list)) {
const DetectByteMathData *bmd = (const DetectByteMathData *)sm->ctx;
if (strcmp(bmd->result, arg) == 0) {
SCLogDebug("Retrieved SM for \"%s\"", arg);
return sm;
}
if (DetectByteMathSMNameMatch(sm, arg)) {
SCLogDebug("Retrieved SM for \"%s\"", arg);
*found_list = list;
return sm;
}
sm = sm->next;
}
Expand Down
3 changes: 2 additions & 1 deletion src/detect-bytemath.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@

void DetectBytemathRegister(void);

SigMatch *DetectByteMathRetrieveSMVar(const char *, int sm_list, const Signature *);
const SigMatch *DetectByteMathRetrieveSMVar(
const char *, int sm_list, int *found_list, const Signature *);
int DetectByteMathDoMatch(DetectEngineThreadCtx *, const DetectByteMathData *, const Signature *,
const uint8_t *, const uint32_t, uint8_t, uint64_t, uint64_t *, uint8_t);

Expand Down
11 changes: 7 additions & 4 deletions src/detect-bytetest.c
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,8 @@ static int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, const char

if (value != NULL) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(value, s, sm_list, &index)) {
if (!DetectByteRetrieveSMVar(value, s, SigMatchStrictEnabled(DETECT_BYTETEST), sm_list,
&index, de_ctx->rule_line)) {
SCLogError("Unknown byte_extract var "
"seen in byte_test - %s",
value);
Expand All @@ -654,10 +655,11 @@ static int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, const char

if (offset != NULL) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(offset, s, sm_list, &index)) {
if (!DetectByteRetrieveSMVar(offset, s, SigMatchStrictEnabled(DETECT_BYTETEST), sm_list,
&index, de_ctx->rule_line)) {
SCLogError("Unknown byte_extract var "
"seen in byte_test - %s",
offset);
value);
goto error;
}
data->offset = index;
Expand All @@ -668,7 +670,8 @@ static int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, const char

if (nbytes != NULL) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(nbytes, s, sm_list, &index)) {
if (!DetectByteRetrieveSMVar(nbytes, s, SigMatchStrictEnabled(DETECT_BYTETEST), sm_list,
&index, de_ctx->rule_line)) {
SCLogError("Unknown byte_extract var "
"seen in byte_test - %s",
nbytes);
Expand Down
3 changes: 2 additions & 1 deletion src/detect-depth.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, const char *
}
if (str[0] != '-' && isalpha((unsigned char)str[0])) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(str, s, -1, &index)) {
if (!DetectByteRetrieveSMVar(
str, s, SigMatchStrictEnabled(DETECT_DEPTH), -1, &index, de_ctx->rule_line)) {
SCLogError("unknown byte_ keyword var "
"seen in depth - %s.",
str);
Expand Down
3 changes: 2 additions & 1 deletion src/detect-distance.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s,
}
if (str[0] != '-' && isalpha((unsigned char)str[0])) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(str, s, -1, &index)) {
if (!DetectByteRetrieveSMVar(str, s, SigMatchStrictEnabled(DETECT_DISTANCE), -1, &index,
de_ctx->rule_line)) {
SCLogError("unknown byte_ keyword var "
"seen in distance - %s",
str);
Expand Down
3 changes: 2 additions & 1 deletion src/detect-isdataat.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,8 @@ int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, const char *isda

if (offset != NULL) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(offset, s, -1, &index)) {
if (!DetectByteRetrieveSMVar(offset, s, SigMatchStrictEnabled(DETECT_ISDATAAT), -1, &index,
de_ctx->rule_line)) {
SCLogError("Unknown byte_extract var "
"seen in isdataat - %s\n",
offset);
Expand Down
3 changes: 2 additions & 1 deletion src/detect-offset.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ int DetectOffsetSetup (DetectEngineCtx *de_ctx, Signature *s, const char *offset
}
if (str[0] != '-' && isalpha((unsigned char)str[0])) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(str, s, -1, &index)) {
if (!DetectByteRetrieveSMVar(
str, s, SigMatchStrictEnabled(DETECT_OFFSET), -1, &index, de_ctx->rule_line)) {
SCLogError("unknown byte_ keyword var "
"seen in offset - %s.",
str);
Expand Down
3 changes: 2 additions & 1 deletion src/detect-within.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ static int DetectWithinSetup(DetectEngineCtx *de_ctx, Signature *s, const char *
}
if (str[0] != '-' && isalpha((unsigned char)str[0])) {
DetectByteIndexType index;
if (!DetectByteRetrieveSMVar(str, s, -1, &index)) {
if (!DetectByteRetrieveSMVar(
str, s, SigMatchStrictEnabled(DETECT_WITHIN), -1, &index, de_ctx->rule_line)) {
SCLogError("unknown byte_ keyword var "
"seen in within - %s",
str);
Expand Down
2 changes: 1 addition & 1 deletion src/util-lua-bytevarlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static int LuaBytevarMap(lua_State *L)
}

DetectByteIndexType idx;
if (!DetectByteRetrieveSMVar(name, s, -1, &idx)) {
if (!DetectByteRetrieveSMVar(name, s, false, -1, &idx, 1)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why rule line 1 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll modify this to use a sentinel value since the line number is meant to indicate the offset into the rule file(s).

luaL_error(L, "unknown byte_extract or byte_math variable: %s", name);
}

Expand Down
Loading