diff --git a/src/detect-dns-query.c b/src/detect-dns-query.c index 3902d828ea..38acf1eaa6 100644 --- a/src/detect-dns-query.c +++ b/src/detect-dns-query.c @@ -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 } diff --git a/src/detect-pcre.c b/src/detect-pcre.c index 8af36fe867..24163c18c1 100644 --- a/src/detect-pcre.c +++ b/src/detect-pcre.c @@ -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); diff --git a/src/detect-pcre.h b/src/detect-pcre.h index 986ca0a3d5..56c62cc3c6 100644 --- a/src/detect-pcre.h +++ b/src/detect-pcre.h @@ -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;