Bug #212 » 0002-fix-relative-contents-with-a-negated-content-for-det.patch
| src/detect-engine-dcepayload.c | ||
|---|---|---|
|                 } 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); | ||
| ... | ... | |
|                         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 " | ||
| ... | ... | |
|     } | ||
|     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); | ||
| ... | ... | |
|     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) | ||
| ... | ... | |
|     UtRegisterTest("DcePayloadParseTest39", DcePayloadParseTest39, 1); | ||
|     UtRegisterTest("DcePayloadParseTest40", DcePayloadParseTest40, 1); | ||
|     UtRegisterTest("DcePayloadParseTest41", DcePayloadParseTest41, 1); | ||
|     UtRegisterTest("DcePayloadTest42", DcePayloadTest42, 1); | ||
| #endif /* UNITTESTS */ | ||
|     return; | ||
| src/detect-engine-uri.c | ||
|---|---|---|
|             } 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); | ||
| ... | ... | |
|                     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); | ||
| ... | ... | |
|         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, | ||
| ... | ... | |
|     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) | ||
| ... | ... | |
|     UtRegisterTest("UriTestSig18", UriTestSig18, 1); | ||
|     UtRegisterTest("UriTestSig19", UriTestSig19, 1); | ||
|     UtRegisterTest("UriTestSig20", UriTestSig20, 1); | ||
|     UtRegisterTest("UriTestSig21", UriTestSig21, 1); | ||
| #endif /* UNITTESTS */ | ||
|     return; | ||