-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
6.0.x: content: don't error out on incomplete hex - v1 #7885
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
* Simple content match part of the detection engine. | ||
*/ | ||
|
||
#include "detect-engine-register.h" | ||
#include "suricata-common.h" | ||
#include "decode.h" | ||
#include "detect.h" | ||
|
@@ -79,8 +80,8 @@ void DetectContentRegister (void) | |
* \retval -1 error | ||
* \retval 0 ok | ||
*/ | ||
int DetectContentDataParse(const char *keyword, const char *contentstr, | ||
uint8_t **pstr, uint16_t *plen) | ||
int DetectContentDataParse( | ||
const char *keyword, const char *contentstr, uint8_t **pstr, uint16_t *plen, bool *warning) | ||
{ | ||
char *str = NULL; | ||
size_t slen = 0; | ||
|
@@ -112,9 +113,18 @@ int DetectContentDataParse(const char *keyword, const char *contentstr, | |
bin_count++; | ||
if (bin) { | ||
if (binpos > 0) { | ||
SCLogError(SC_ERR_INVALID_SIGNATURE, | ||
"Incomplete hex code in content - %s. Invalidating signature.", | ||
SCLogWarning(SC_ERR_INVALID_SIGNATURE, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should only be a warning if we're not in strict mode. If we are in strict mode it should be an error like it was. |
||
"Incomplete hex code in content - %s. Invalidating signature. " | ||
"This will become an error in 7.0.", | ||
contentstr); | ||
/* Prior to 6.0.6, incomplete hex was silently | ||
ignored. With 6.0.6 this turned into an | ||
error with -T. For 6.0.7, make the error | ||
non-fatal unless strict content parsing is | ||
enabled. */ | ||
if (warning != NULL && !SigMatchStrictEnabled(DETECT_CONTENT)) { | ||
*warning = true; | ||
} | ||
goto error; | ||
} | ||
bin = 0; | ||
|
@@ -202,20 +212,21 @@ int DetectContentDataParse(const char *keyword, const char *contentstr, | |
error: | ||
return -1; | ||
} | ||
|
||
/** | ||
* \brief DetectContentParse | ||
* \initonly | ||
*/ | ||
DetectContentData *DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx, | ||
const char *contentstr) | ||
DetectContentData *DetectContentParse( | ||
SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr, bool *warning) | ||
{ | ||
DetectContentData *cd = NULL; | ||
uint8_t *content = NULL; | ||
uint16_t len = 0; | ||
int ret; | ||
|
||
ret = DetectContentDataParse("content", contentstr, &content, &len); | ||
if (ret == -1) { | ||
ret = DetectContentDataParse("content", contentstr, &content, &len, warning); | ||
if (ret < 0) { | ||
return NULL; | ||
} | ||
|
||
|
@@ -253,7 +264,7 @@ DetectContentData *DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx, | |
DetectContentData *DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx, | ||
const char *contentstr) | ||
{ | ||
return DetectContentParse(spm_global_thread_ctx, contentstr); | ||
return DetectContentParse(spm_global_thread_ctx, contentstr, NULL); | ||
} | ||
|
||
/** | ||
|
@@ -329,8 +340,9 @@ int DetectContentSetup(DetectEngineCtx *de_ctx, Signature *s, const char *conten | |
{ | ||
DetectContentData *cd = NULL; | ||
SigMatch *sm = NULL; | ||
bool warning = false; | ||
|
||
cd = DetectContentParse(de_ctx->spm_global_thread_ctx, contentstr); | ||
cd = DetectContentParse(de_ctx->spm_global_thread_ctx, contentstr, &warning); | ||
if (cd == NULL) | ||
goto error; | ||
if (s->init_data->negated == true) { | ||
|
@@ -369,6 +381,8 @@ int DetectContentSetup(DetectEngineCtx *de_ctx, Signature *s, const char *conten | |
|
||
error: | ||
DetectContentFree(de_ctx, cd); | ||
if (warning) | ||
return 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will this not load the rule, but minus the broken content condition? so effectively turning There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we should either return -2 or -3 here (not sure which though): int ret = SigParse(de_ctx, sig, sigstr, dir, &parser);
if (ret == -3) {
de_ctx->sigerror_silent = true;
de_ctx->sigerror_ok = true;
goto error;
}
else if (ret == -2) {
de_ctx->sigerror_silent = true;
goto error;
} else if (ret < 0) {
goto error;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, its a -4... New.. Log the error, but don't error out. An option we don't have it. Which handles the previous case as well. ie)
|
||
return -1; | ||
} | ||
|
||
|
@@ -796,7 +810,7 @@ static int DetectContentParseTest01 (void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd != NULL) { | ||
if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) { | ||
SCLogDebug("expected %s got ", teststringparsed); | ||
|
@@ -827,7 +841,7 @@ static int DetectContentParseTest02 (void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd != NULL) { | ||
if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) { | ||
SCLogDebug("expected %s got ", teststringparsed); | ||
|
@@ -858,7 +872,7 @@ static int DetectContentParseTest03 (void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd != NULL) { | ||
if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) { | ||
SCLogDebug("expected %s got ", teststringparsed); | ||
|
@@ -889,7 +903,7 @@ static int DetectContentParseTest04 (void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd != NULL) { | ||
uint16_t len = (cd->content_len > strlen(teststringparsed)); | ||
if (memcmp(cd->content, teststringparsed, len) != 0) { | ||
|
@@ -920,7 +934,7 @@ static int DetectContentParseTest05 (void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd != NULL) { | ||
SCLogDebug("expected NULL got "); | ||
PrintRawUriFp(stdout,cd->content,cd->content_len); | ||
|
@@ -946,7 +960,7 @@ static int DetectContentParseTest06 (void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd != NULL) { | ||
uint16_t len = (cd->content_len > strlen(teststringparsed)); | ||
if (memcmp(cd->content, teststringparsed, len) != 0) { | ||
|
@@ -977,7 +991,7 @@ static int DetectContentParseTest07 (void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd != NULL) { | ||
SCLogDebug("expected NULL got %p: ", cd); | ||
result = 0; | ||
|
@@ -1000,7 +1014,7 @@ static int DetectContentParseTest08 (void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd != NULL) { | ||
SCLogDebug("expected NULL got %p: ", cd); | ||
result = 0; | ||
|
@@ -1288,7 +1302,7 @@ static int DetectContentParseTest09(void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
FAIL_IF_NULL(cd); | ||
DetectContentFree(NULL, cd); | ||
SpmDestroyGlobalThreadCtx(spm_global_thread_ctx); | ||
|
@@ -2373,7 +2387,7 @@ static int DetectContentParseTest41(void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd == NULL) { | ||
SCLogDebug("expected not NULL"); | ||
result = 0; | ||
|
@@ -2406,7 +2420,7 @@ static int DetectContentParseTest42(void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd == NULL) { | ||
SCLogDebug("expected not NULL"); | ||
result = 0; | ||
|
@@ -2440,7 +2454,7 @@ static int DetectContentParseTest43(void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd == NULL) { | ||
SCLogDebug("expected not NULL"); | ||
result = 0; | ||
|
@@ -2477,7 +2491,7 @@ static int DetectContentParseTest44(void) | |
SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher); | ||
FAIL_IF(spm_global_thread_ctx == NULL); | ||
|
||
cd = DetectContentParse(spm_global_thread_ctx, teststring); | ||
cd = DetectContentParse(spm_global_thread_ctx, teststring, NULL); | ||
if (cd == NULL) { | ||
SCLogDebug("expected not NULL"); | ||
result = 0; | ||
|
@@ -3030,8 +3044,26 @@ static int DetectLongContentTest3(void) | |
return !DetectLongContentTestCommon(sig, 1); | ||
} | ||
|
||
static int DetectBadBinContent(void) | ||
static int DetectIncompleteHexNonStrict(void) | ||
{ | ||
DetectEngineCtx *de_ctx = NULL; | ||
de_ctx = DetectEngineCtxInit(); | ||
FAIL_IF_NULL(de_ctx); | ||
de_ctx->flags |= DE_QUIET; | ||
FAIL_IF_NULL(DetectEngineAppendSig( | ||
de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|a|\"; sid:1;)")); | ||
FAIL_IF_NULL(DetectEngineAppendSig( | ||
de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|aa b|\"; sid:2;)")); | ||
/* https://redmine.openinfosecfoundation.org/issues/5201 */ | ||
FAIL_IF_NULL(DetectEngineAppendSig( | ||
de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|22 2 22|\"; sid:3;)")); | ||
DetectEngineCtxFree(de_ctx); | ||
PASS; | ||
} | ||
|
||
static int DetectIncompleteHexStrict(void) | ||
{ | ||
SigTableApplyStrictCommandlineOption("content"); | ||
DetectEngineCtx *de_ctx = NULL; | ||
de_ctx = DetectEngineCtxInit(); | ||
FAIL_IF_NULL(de_ctx); | ||
|
@@ -3040,15 +3072,35 @@ static int DetectBadBinContent(void) | |
de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|a|\"; sid:1;)")); | ||
FAIL_IF_NOT_NULL(DetectEngineAppendSig( | ||
de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|aa b|\"; sid:1;)")); | ||
FAIL_IF_NOT_NULL(DetectEngineAppendSig( | ||
de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|aa bz|\"; sid:1;)")); | ||
/* https://redmine.openinfosecfoundation.org/issues/5201 */ | ||
FAIL_IF_NOT_NULL(DetectEngineAppendSig( | ||
de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|22 2 22|\"; sid:1;)")); | ||
DetectEngineCtxFree(de_ctx); | ||
PASS; | ||
} | ||
|
||
/** | ||
* This is a bit of hack, to cleanup from DetectIncompleteHexStrict if | ||
* it fails, to avoid causing other tests to fail. | ||
*/ | ||
static int DetectIncompleteHexStrictCleanup(void) | ||
{ | ||
SigTableClearStrictOption("content"); | ||
PASS; | ||
} | ||
|
||
static int DetectBadHexContent(void) | ||
{ | ||
DetectEngineCtx *de_ctx = NULL; | ||
de_ctx = DetectEngineCtxInit(); | ||
FAIL_IF_NULL(de_ctx); | ||
de_ctx->flags |= DE_QUIET; | ||
FAIL_IF_NOT_NULL(DetectEngineAppendSig( | ||
de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|aa bz|\"; sid:1;)")); | ||
DetectEngineCtxFree(de_ctx); | ||
PASS; | ||
} | ||
|
||
/** | ||
* \brief this function registers unit tests for DetectContent | ||
*/ | ||
|
@@ -3168,6 +3220,9 @@ static void DetectContentRegisterTests(void) | |
UtRegisterTest("DetectLongContentTest2", DetectLongContentTest2); | ||
UtRegisterTest("DetectLongContentTest3", DetectLongContentTest3); | ||
|
||
UtRegisterTest("DetectBadBinContent", DetectBadBinContent); | ||
UtRegisterTest("DetectBadHexContent", DetectBadHexContent); | ||
UtRegisterTest("DetectIncompleteHexNonStrict", DetectIncompleteHexNonStrict); | ||
UtRegisterTest("DetectIncompleteHexStrict", DetectIncompleteHexStrict); | ||
UtRegisterTest("DetectIncompleteHexStrictCleanup", DetectIncompleteHexStrictCleanup); | ||
} | ||
#endif /* UNITTESTS */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,7 +149,7 @@ static DetectFileextData *DetectFileextParse (DetectEngineCtx *de_ctx, const cha | |
|
||
memset(fileext, 0x00, sizeof(DetectFileextData)); | ||
|
||
if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len) == -1) { | ||
if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len, NULL) == -1) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess these other users of content parsing should respect the same behaviour. |
||
goto error; | ||
} | ||
uint16_t u; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An output var just seemed more appropriate here than changing the return value.