DNS: add /F modifier to pcre to inspect DNS query name

pull/412/merge
Victor Julien 13 years ago
parent 4f20f72f4d
commit 4817e1305f

@ -738,6 +738,102 @@ end:
UTHFreePacket(p4);
return result;
}
/** \test simple google.com query matching, pcre */
static int DetectDnsQueryTest06(void) {
/* google.com */
uint8_t buf[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
0x00, 0x10, 0x00, 0x01, };
int result = 0;
Flow f;
DNSState *dns_state = NULL;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars tv;
DetectEngineThreadCtx *det_ctx = NULL;
memset(&tv, 0, sizeof(ThreadVars));
memset(&f, 0, sizeof(Flow));
p = UTHBuildPacket(buf, sizeof(buf), IPPROTO_UDP);
FLOW_INITIALIZE(&f);
f.flags |= FLOW_IPV4;
f.proto = IPPROTO_UDP;
p->flow = &f;
p->flags |= PKT_HAS_FLOW;
p->flowflags |= FLOW_PKT_TOSERVER;
f.alproto = ALPROTO_DNS_UDP;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
de_ctx->mpm_matcher = MPM_AC;
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
"(msg:\"Test dns_query option\"; "
"content:\"google\"; nocase; dns_query; "
"pcre:\"/google\\.com$/iF\"; sid:1;)");
if (s == NULL) {
goto end;
}
s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
"(msg:\"Test dns_query option\"; "
"content:\"google\"; nocase; dns_query; "
"pcre:\"/^\\.[a-z]{2,3}$/iRF\"; sid:2;)");
if (s == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(NULL, &f, ALPROTO_DNS_UDP, STREAM_TOSERVER, buf, sizeof(buf));
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
goto end;
}
dns_state = f.alstate;
if (dns_state == NULL) {
printf("no dns state: ");
goto end;
}
/* do detect */
SigMatchSignatures(&tv, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sig 1 didn't alert, but it should have: ");
goto end;
}
if (!(PacketAlertCheck(p, 2))) {
printf("sig 2 didn't alert, but it should have: ");
goto end;
}
result = 1;
end:
if (det_ctx != NULL)
DetectEngineThreadCtxDeinit(&tv, det_ctx);
if (de_ctx != NULL)
SigGroupCleanup(de_ctx);
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
FLOW_DESTROY(&f);
UTHFreePacket(p);
return result;
}
#endif
static void DetectDnsQueryRegisterTests(void) {
@ -747,5 +843,6 @@ static void DetectDnsQueryRegisterTests(void) {
UtRegisterTest("DetectDnsQueryTest03 -- tcp", DetectDnsQueryTest03, 1);
UtRegisterTest("DetectDnsQueryTest04 -- tcp splicing", DetectDnsQueryTest04, 1);
UtRegisterTest("DetectDnsQueryTest05 -- tcp splicing/multi tx", DetectDnsQueryTest05, 1);
UtRegisterTest("DetectDnsQueryTest06 -- pcre", DetectDnsQueryTest06, 1);
#endif
}

@ -471,6 +471,10 @@ DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx, char *regexstr)
/* snort's option */
pd->flags |= DETECT_PCRE_HTTP_STAT_CODE;
break;
case 'F':
/* suricata extension (dns query name) */
pd->flags |= DETECT_PCRE_DNS_QUERY;
break;
default:
SCLogError(SC_ERR_UNKNOWN_REGEX_MOD, "unknown regex modifier '%c'", *op);
goto error;
@ -693,6 +697,22 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst
}
}
if (pd->flags & DETECT_PCRE_DNS_QUERY) {
if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_DNS) {
SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "Invalid option. "
"Conflicting alprotos detected for this rule. Dns "
"pcre modifier found along with a different protocol "
"for the rule.");
goto error;
}
if (s->init_flags & (SIG_FLAG_INIT_FILE_DATA | SIG_FLAG_INIT_DCE_STUB_DATA)) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "pcre found with dns "
"modifier set, with file_data/dce_stub_data sticky "
"option set.");
goto error;
}
}
int sm_list;
if (s->init_flags & SIG_FLAG_INIT_FILE_DATA) {
SCLogDebug("adding to http server body list because of file data");
@ -766,6 +786,11 @@ static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, char *regexst
s->flags |= SIG_FLAG_APPLAYER;
s->alproto = ALPROTO_HTTP;
sm_list = DETECT_SM_LIST_HUADMATCH;
} else if (pd->flags & DETECT_PCRE_DNS_QUERY) {
SCLogDebug("DNS query inspection modifier set on pcre");
s->flags |= SIG_FLAG_APPLAYER;
s->alproto = ALPROTO_DNS;
sm_list = DETECT_SM_LIST_DNSQUERY_MATCH;
} else {
sm_list = DETECT_SM_LIST_PMATCH;
}
@ -1639,6 +1664,35 @@ int DetectPcreParseTest25(void)
return result;
}
/** \test Check a signature with inconsistent pcre modifiers */
static int DetectPcreParseTest26(void)
{
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if ( (de_ctx = DetectEngineCtxInit()) == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx,
"alert http any any -> any any "
"(msg:\"Testing inconsistent pcre modifiers\"; "
"pcre:\"/abc/F\"; sid:1;)");
if (de_ctx->sig_list == NULL) {
result = 1;
} else {
printf("sig parse should have failed: ");
}
end:
if (de_ctx != NULL)
SigCleanSignatures(de_ctx);
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
static int DetectPcreTestSig01Real(int mpm_type) {
uint8_t *buf = (uint8_t *)
"GET /one/ HTTP/1.1\r\n"
@ -3860,6 +3914,7 @@ void DetectPcreRegisterTests(void) {
UtRegisterTest("DetectPcreParseTest23", DetectPcreParseTest23, 1);
UtRegisterTest("DetectPcreParseTest24", DetectPcreParseTest24, 1);
UtRegisterTest("DetectPcreParseTest25", DetectPcreParseTest25, 1);
UtRegisterTest("DetectPcreParseTest26", DetectPcreParseTest26, 1);
UtRegisterTest("DetectPcreTestSig01B2g -- pcre test", DetectPcreTestSig01B2g, 1);
UtRegisterTest("DetectPcreTestSig01B3g -- pcre test", DetectPcreTestSig01B3g, 1);

@ -52,6 +52,8 @@
#define DETECT_PCRE_NEGATE 0x80000
#define DETECT_PCRE_CASELESS 0x100000
#define DETECT_PCRE_DNS_QUERY 0x200000
typedef struct DetectPcreData_ {
/* pcre options */
pcre *re;

Loading…
Cancel
Save