detect-dsize: Add ! operator for dsize matching

pull/6324/head
Joshua Lumb 6 years ago committed by Victor Julien
parent 9b8be5a650
commit cf9b2b5fd1

@ -290,18 +290,20 @@ dsize
With the dsize keyword, you can match on the size of the packet
payload. You can use the keyword for example to look for abnormal
sizes of payloads. This may be convenient in detecting buffer
overflows.
sizes of payloads which are equal to some n i.e. 'dsize:n'
not equal 'dsize:!n' less than 'dsize:<n' or greater than 'dsize:>n'
This may be convenient in detecting buffer overflows.
Format::
dsize:<number>;
dsize:[<>!]number; || dsize:min<>max;
Example of dsize in a rule:
.. container:: example-rule
alert udp $EXTERNAL_NET any -> $HOME_NET 65535 (msg:"GPL DELETED EXPLOIT LANDesk Management Suite Alerting Service buffer overflow"; :example-rule-emphasis:`dsize:>268;` reference: bugtraq,23483; reference: cve,2007-1674; classtype: attempted-admin; sid:100000928; rev:1;)
alert tcp $EXTERNAL_NET any -> $HOME_NET 8081 (msg:"Example Negation"; :example-rule-emphasis:`dsize:!10;` sid:123; rev:1;)
byte_test
---------

@ -44,9 +44,9 @@
#include "util-profiling.h"
/**
* dsize:[<>]<0-65535>[<><0-65535>];
* dsize:[<>!]<0-65535>[<><0-65535>];
*/
#define PARSE_REGEX "^\\s*(<|>)?\\s*([0-9]{1,5})\\s*(?:(<>)\\s*([0-9]{1,5}))?\\s*$"
#define PARSE_REGEX "^\\s*(<|>|!)?\\s*([0-9]{1,5})\\s*(?:(<>)\\s*([0-9]{1,5}))?\\s*$"
static DetectParseRegex parse_regex;
static int DetectDsizeMatch (DetectEngineThreadCtx *, Packet *,
@ -92,6 +92,8 @@ DsizeMatch(const uint16_t psize, const uint8_t mode,
return 1;
else if (mode == DETECTDSIZE_RA && psize > dsize && psize < dsize2)
return 1;
else if (mode == DETECTDSIZE_NE && dsize != psize)
return 1;
return 0;
}
@ -190,16 +192,7 @@ static DetectDsizeData *DetectDsizeParse (const char *rawstr)
goto error;
dd->dsize = 0;
dd->dsize2 = 0;
dd->mode = DETECTDSIZE_EQ; // default
if (strlen(mode) > 0) {
if (mode[0] == '<')
dd->mode = DETECTDSIZE_LT;
else if (mode[0] == '>')
dd->mode = DETECTDSIZE_GT;
else
dd->mode = DETECTDSIZE_EQ;
}
dd->mode = 0;
if (strcmp("<>", range) == 0) {
if (strlen(mode) != 0) {
@ -207,6 +200,17 @@ static DetectDsizeData *DetectDsizeParse (const char *rawstr)
goto error;
}
dd->mode = DETECTDSIZE_RA;
} else if (strlen(mode) > 0) {
if (mode[0] == '<')
dd->mode = DETECTDSIZE_LT;
else if (mode[0] == '>')
dd->mode = DETECTDSIZE_GT;
else if (mode[0] == '!')
dd->mode = DETECTDSIZE_NE;
else
dd->mode = DETECTDSIZE_EQ;
} else {
dd->mode = DETECTDSIZE_EQ; // default
}
/** set the first dsize value */
@ -387,6 +391,7 @@ int SigParseGetMaxDsize(const Signature *s)
switch (dd->mode) {
case DETECTDSIZE_LT:
case DETECTDSIZE_EQ:
case DETECTDSIZE_NE:
return dd->dsize;
case DETECTDSIZE_RA:
return dd->dsize2;
@ -415,6 +420,7 @@ void SigParseSetDsizePair(Signature *s)
high = dd->dsize;
break;
case DETECTDSIZE_EQ:
case DETECTDSIZE_NE:
low = dd->dsize;
high = dd->dsize;
break;
@ -427,10 +433,11 @@ void SigParseSetDsizePair(Signature *s)
high = 65535;
break;
}
s->dsize_mode = dd->mode;
s->dsize_low = low;
s->dsize_high = high;
SCLogDebug("low %u, high %u", low, high);
SCLogDebug("low %u, high %u, mode %u", low, high, dd->mode);
}
}
@ -866,6 +873,89 @@ static int DsizeTestParse20 (void)
return result;
}
/**
* \test this is a test for a valid dsize value !1
*
* \retval 1 on success
* \retval 0 on failure
*/
static int DsizeTestParse21(void)
{
DetectDsizeData *dd = NULL;
dd = DetectDsizeParse("!1");
FAIL_IF_NULL(dd);
DetectDsizeFree(NULL, dd);
PASS;
}
/**
* \test this is a test for a valid dsize value ! 1
*
* \retval 1 on success
* \retval 0 on failure
*/
static int DsizeTestParse22(void)
{
DetectDsizeData *dd = NULL;
dd = DetectDsizeParse("! 1");
FAIL_IF_NULL(dd);
DetectDsizeFree(NULL, dd);
PASS;
}
/**
* \test this is a test for a invalid dsize value 1!
*
* \retval 1 on success
* \retval 0 on failure
*/
static int DsizeTestParse23(void)
{
DetectDsizeData *dd = NULL;
dd = DetectDsizeParse("1!");
if (dd) {
DetectDsizeFree(NULL, dd);
FAIL;
}
PASS;
}
/**
* \test this is a test for positive ! dsize matching
*
* \retval 1 on success
* \retval 0 on failure
*/
static int DsizeTestMatch01(void)
{
uint16_t psize = 1;
uint16_t dsizelow = 2;
uint16_t dsizehigh = 0;
int result = 0;
result = DsizeMatch(psize, DETECTDSIZE_NE, dsizelow, dsizehigh);
PASS_IF(result);
}
/**
* \test this is a test for negative ! dsize matching
*
* \retval 1 on success
* \retval 0 on failure
*/
static int DsizeTestMatch02(void)
{
uint16_t psize = 1;
uint16_t dsizelow = 1;
uint16_t dsizehigh = 0;
int result = 0;
result = !DsizeMatch(psize, DETECTDSIZE_NE, dsizelow, dsizehigh);
PASS_IF(result);
}
/**
* \test DetectDsizeIcmpv6Test01 is a test for checking the working of
* dsize keyword by creating 2 rules and matching a crafted packet
@ -984,6 +1074,11 @@ static void DsizeRegisterTests(void)
UtRegisterTest("DsizeTestParse18", DsizeTestParse18);
UtRegisterTest("DsizeTestParse19", DsizeTestParse19);
UtRegisterTest("DsizeTestParse20", DsizeTestParse20);
UtRegisterTest("DsizeTestParse21", DsizeTestParse21);
UtRegisterTest("DsizeTestParse22", DsizeTestParse22);
UtRegisterTest("DsizeTestParse23", DsizeTestParse23);
UtRegisterTest("DsizeTestMatch01", DsizeTestMatch01);
UtRegisterTest("DsizeTestMatch02", DsizeTestMatch02);
UtRegisterTest("DetectDsizeIcmpv6Test01", DetectDsizeIcmpv6Test01);
}

@ -28,6 +28,7 @@
#define DETECTDSIZE_EQ 1
#define DETECTDSIZE_GT 2
#define DETECTDSIZE_RA 3
#define DETECTDSIZE_NE 4
typedef struct DetectDsizeData_ {
uint16_t dsize;
@ -42,5 +43,21 @@ int SigParseGetMaxDsize(const Signature *s);
void SigParseSetDsizePair(Signature *s);
void SigParseApplyDsizeToContent(Signature *s);
/** Determine if a packet p should be kicked out during prefilter due
* to dsize outside the range specified in signature s */
static inline bool SigDsizePrefilter(const Packet *p, const Signature *s, uint32_t sflags)
{
if (unlikely(sflags & SIG_FLAG_DSIZE)) {
if (likely(p->payload_len < s->dsize_low || p->payload_len > s->dsize_high)) {
if (!(s->dsize_mode == DETECTDSIZE_NE)) {
SCLogDebug("kicked out as p->payload_len %u, dsize low %u, hi %u", p->payload_len,
s->dsize_low, s->dsize_high);
return true;
}
}
}
return false;
}
#endif /* __DETECT_DSIZE_H__ */

@ -534,26 +534,23 @@ static int SignatureCreateMask(Signature *s)
case DETECT_DSIZE:
{
DetectDsizeData *ds = (DetectDsizeData *)sm->ctx;
switch (ds->mode) {
case DETECTDSIZE_LT:
/* LT will include 0, so no payload.
* if GT is used in the same rule the
* flag will be set anyway. */
break;
case DETECTDSIZE_RA:
case DETECTDSIZE_GT:
/* LT will include 0, so no payload.
* if GT is used in the same rule the
* flag will be set anyway. */
if (ds->mode == DETECTDSIZE_RA || ds->mode == DETECTDSIZE_GT ||
ds->mode == DETECTDSIZE_NE) {
s->mask |= SIG_MASK_REQUIRE_PAYLOAD;
SCLogDebug("sig requires payload");
} else if (ds->mode == DETECTDSIZE_EQ) {
if (ds->dsize > 0) {
s->mask |= SIG_MASK_REQUIRE_PAYLOAD;
SCLogDebug("sig requires payload");
break;
case DETECTDSIZE_EQ:
if (ds->dsize > 0) {
s->mask |= SIG_MASK_REQUIRE_PAYLOAD;
SCLogDebug("sig requires payload");
} else if (ds->dsize == 0) {
s->mask |= SIG_MASK_REQUIRE_NO_PAYLOAD;
SCLogDebug("sig requires no payload");
}
break;
} else {
s->mask |= SIG_MASK_REQUIRE_NO_PAYLOAD;
SCLogDebug("sig requires no payload");
}
}
break;
}

@ -34,6 +34,7 @@
#include "app-layer-parser.h"
#include "detect.h"
#include "detect-dsize.h"
#include "detect-engine.h"
#include "detect-engine-profile.h"
@ -769,13 +770,8 @@ static inline void DetectRulePacketRules(
goto next;
}
if (unlikely(sflags & SIG_FLAG_DSIZE)) {
if (likely(p->payload_len < s->dsize_low || p->payload_len > s->dsize_high)) {
SCLogDebug("kicked out as p->payload_len %u, dsize low %u, hi %u",
p->payload_len, s->dsize_low, s->dsize_high);
goto next;
}
}
if (SigDsizePrefilter(p, s, sflags))
goto next;
/* if the sig has alproto and the session as well they should match */
if (likely(sflags & SIG_FLAG_APPLAYER)) {

@ -522,6 +522,7 @@ typedef struct Signature_ {
uint16_t dsize_low;
uint16_t dsize_high;
uint8_t dsize_mode;
SignatureMask mask;
SigIntId num; /**< signature number, internal id */

Loading…
Cancel
Save