From f35fab863d91d73ac07fa985a96e434bb05fcb2e Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Fri, 16 Jul 2010 21:21:20 +0530 Subject: [PATCH 2/2] fix relative contents with a negated content for detect-engine-(uri|dcepayload).c like how we did for detect-engine-payload.c --- src/detect-engine-dcepayload.c | 109 +++++++++++++++++++++++++++++++++++++++- src/detect-engine-uri.c | 102 ++++++++++++++++++++++++++++++++++++- 2 files changed, 208 insertions(+), 3 deletions(-) diff --git a/src/detect-engine-dcepayload.c b/src/detect-engine-dcepayload.c index 6f7ecb7..55437b6 100644 --- a/src/detect-engine-dcepayload.c +++ b/src/detect-engine-dcepayload.c @@ -216,9 +216,9 @@ static int DoInspectDcePayload(DetectEngineCtx *de_ctx, } else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) { goto match; } else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) { - match_offset = (uint32_t)((found - stub) + cd->content_len); SCLogDebug("content %"PRIu32" matched at offset %"PRIu32", but " "negated so no match", cd->id, match_offset); + det_ctx->discontinue_matching = 1; SCReturnInt(0); } else { match_offset = (uint32_t)((found - stub) + cd->content_len); @@ -243,6 +243,9 @@ static int DoInspectDcePayload(DetectEngineCtx *de_ctx, SCReturnInt(1); } + if (det_ctx->discontinue_matching) + SCReturnInt(0); + /* set the previous match offset to the start of this match + 1 */ prev_offset = (match_offset - (cd->content_len - 1)); SCLogDebug("trying to see if there is another match after " @@ -408,6 +411,7 @@ int DetectEngineInspectDcePayload(DetectEngineCtx *de_ctx, } det_ctx->payload_offset = 0; + det_ctx->discontinue_matching = 0; r = DoInspectDcePayload(de_ctx, det_ctx, s, s->dmatch, f, dce_stub_data, dce_stub_data_len, dcerpc_state); @@ -9909,6 +9913,107 @@ int DcePayloadParseTest41(void) return result; } +/** + * \test Test the working of consecutive relative matches with a negated content. + */ +int DcePayloadTest42(void) +{ + int result = 0; + + uint8_t request1[] = { + 0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, + 0x77, 0x65, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, /* "we need " */ + 0x74, 0x6f, 0x20, 0x66, 0x69, 0x78, 0x20, 0x74, /* "to fix t" */ + 0x68, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, /* "his and " */ + 0x79, 0x65, 0x73, 0x20, 0x66, 0x69, 0x78, 0x20, /* "yes fix " */ + 0x74, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77 /* "this now" */ + }; + uint32_t request1_len = sizeof(request1); + + TcpSession ssn; + Packet p; + ThreadVars tv; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + Flow f; + int r; + + char *sig1 = "alert tcp any any -> any any " + "(msg:\"testing dce consecutive relative matches\"; dce_stub_data; " + "content:fix; distance:0; content:this; within:6; " + "content:!\"and\"; distance:0; sid:1;)"; + + Signature *s; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + memset(&p, 0, sizeof(Packet)); + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = NULL; + p.payload_len = 0; + p.proto = IPPROTO_TCP; + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + f.alproto = ALPROTO_DCERPC; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, sig1); + s = de_ctx->sig_list; + if (s == NULL) + goto end; + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + /* request 1 */ + r = AppLayerParse(&f, ALPROTO_DCERPC, STREAM_TOSERVER, request1, request1_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + result = 0; + goto end; + } + /* detection phase */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + if ((PacketAlertCheck(&p, 1))) { + printf("sid 1 matched but shouldn't have for packet: "); + goto end; + } + + result = 1; + +end: + if (de_ctx != NULL) { + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + } + + FlowL7DataPtrFree(&f); + StreamTcpFreeConfig(TRUE); + + return result; +} + #endif /* UNITTESTS */ void DcePayloadRegisterTests(void) @@ -9957,6 +10062,8 @@ void DcePayloadRegisterTests(void) UtRegisterTest("DcePayloadParseTest39", DcePayloadParseTest39, 1); UtRegisterTest("DcePayloadParseTest40", DcePayloadParseTest40, 1); UtRegisterTest("DcePayloadParseTest41", DcePayloadParseTest41, 1); + + UtRegisterTest("DcePayloadTest42", DcePayloadTest42, 1); #endif /* UNITTESTS */ return; diff --git a/src/detect-engine-uri.c b/src/detect-engine-uri.c index c1b70b7..d9ce18a 100644 --- a/src/detect-engine-uri.c +++ b/src/detect-engine-uri.c @@ -204,9 +204,8 @@ static int DoInspectPacketUri(DetectEngineCtx *de_ctx, } else if (found == NULL && ud->flags & DETECT_URICONTENT_NEGATED) { goto match; } else if (found != NULL && ud->flags & DETECT_URICONTENT_NEGATED) { - /* why are we saving match offset here? */ - match_offset = (uint32_t)((found - payload) + ud->uricontent_len); SCLogDebug("uricontent %"PRIu32" matched at offset %"PRIu32", but negated so no match", ud->id, match_offset); + det_ctx->discontinue_matching = 1; SCReturnInt(0); } else { match_offset = (uint32_t)((found - payload) + ud->uricontent_len); @@ -229,6 +228,9 @@ static int DoInspectPacketUri(DetectEngineCtx *de_ctx, SCReturnInt(1); } + if (det_ctx->discontinue_matching) + SCReturnInt(0); + /* set the previous match offset to the start of this match + 1 */ prev_offset = (match_offset - (ud->uricontent_len - 1)); SCLogDebug("trying to see if there is another match after prev_offset %"PRIu32, prev_offset); @@ -391,6 +393,8 @@ int DetectEngineInspectPacketUris(DetectEngineCtx *de_ctx, if (tx == NULL || tx->request_uri_normalized == NULL) continue; + det_ctx->discontinue_matching = 0; + /* Inspect all the uricontents fetched on each * transaction at the app layer */ r = DoInspectPacketUri(de_ctx, det_ctx, s, s->umatch, @@ -2687,6 +2691,99 @@ end: return result; } +/** + * \test Test multiple relative contents with a negated content. + */ +static int UriTestSig21(void) +{ + int result = 0; + uint8_t *http_buf = (uint8_t *)"POST /we_need_to_fix_this_and_yes_fix_this_now HTTP/1.0\r\n" + "User-Agent: Mozilla/1.0\r\n"; + uint32_t http_buf_len = strlen((char *)http_buf); + Flow f; + TcpSession ssn; + HtpState *http_state = NULL; + Packet p; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + memset(&f, 0, sizeof(Flow)); + memset(&ssn, 0, sizeof(TcpSession)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = http_buf; + p.payload_len = http_buf_len; + p.proto = IPPROTO_TCP; + + FLOW_INITIALIZE(&f); + f.protoctx = (void *)&ssn; + f.src.family = AF_INET; + f.dst.family = AF_INET; + + p.flow = &f; + p.flowflags |= FLOW_PKT_TOSERVER; + p.flowflags |= FLOW_PKT_ESTABLISHED; + f.alproto = ALPROTO_HTTP; + + StreamTcpInitConfig(TRUE); + FlowL7DataPtrInit(&f); + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"test multiple relative uricontents\"; " + "uricontent:fix; uricontent:this; within:6; " + "uricontent:!\"and\"; distance:0; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf, http_buf_len); + if (r != 0) { + printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); + goto end; + } + + http_state = f.aldata[AlpGetStateIdx(ALPROTO_HTTP)]; + if (http_state == NULL) { + printf("no http state: "); + goto end; + } + + /* do detect */ + SigMatchSignatures(&tv, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 alerted, but it should not: "); + 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); + + StreamTcpFreeConfig(TRUE); + FLOW_DESTROY(&f); + return result; +} + #endif /* UNITTESTS */ void UriRegisterTests(void) @@ -2713,6 +2810,7 @@ void UriRegisterTests(void) UtRegisterTest("UriTestSig18", UriTestSig18, 1); UtRegisterTest("UriTestSig19", UriTestSig19, 1); UtRegisterTest("UriTestSig20", UriTestSig20, 1); + UtRegisterTest("UriTestSig21", UriTestSig21, 1); #endif /* UNITTESTS */ return; -- 1.7.0.2