Bug #155 » 0001-add-pcre-with-U-modifiers-to-the-umatch-sigmatch-lis.patch
| src/detect-engine-uri.c | ||
|---|---|---|
|
#include "decode.h"
|
||
|
#include "detect.h"
|
||
|
#include "detect-engine.h"
|
||
|
#include "detect-parse.h"
|
||
|
#include "detect-engine-state.h"
|
||
|
#include "detect-uricontent.h"
|
||
|
#include "detect-pcre.h"
|
||
|
#include "detect-isdataat.h"
|
||
|
#include "detect-bytetest.h"
|
||
|
#include "detect-bytejump.h"
|
||
|
#include "flow-util.h"
|
||
|
#include "util-spm.h"
|
||
|
#include "util-debug.h"
|
||
|
#include "util-print.h"
|
||
| ... | ... | |
|
#include "app-layer-htp.h"
|
||
|
#include "app-layer-protos.h"
|
||
|
/** \brief Run the actual payload match function for uricontent
|
||
|
/**
|
||
|
* \brief Run the actual payload match function for uricontent.
|
||
|
*
|
||
|
* For accounting the last match in relative matching the
|
||
|
* det_ctx->uricontent_payload_offset int is used.
|
||
|
* For accounting the last match in relative matching the
|
||
|
* det_ctx->payload_offset int is used.
|
||
|
*
|
||
|
* \param de_ctx Detection engine context
|
||
|
* \param det_ctx Detection engine thread context
|
||
|
* \param s Signature to inspect
|
||
|
* \param sm SigMatch to inspect
|
||
|
* \param payload ptr to the uricontent payload to inspect
|
||
|
* \param payload_len length of the uricontent payload
|
||
|
* \param de_ctx Detection engine context.
|
||
|
* \param det_ctx Detection engine thread context.
|
||
|
* \param s Signature to inspect.
|
||
|
* \param sm SigMatch to inspect.
|
||
|
* \param payload Ptr to the uricontent payload to inspect.
|
||
|
* \param payload_len Length of the uricontent payload.
|
||
|
*
|
||
|
* \retval 0 no match
|
||
|
* \retval 1 match
|
||
|
* \retval 0 no match.
|
||
|
* \retval 1 match.
|
||
|
*/
|
||
|
static int DoInspectPacketUri(DetectEngineCtx *de_ctx,
|
||
|
DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch *sm,
|
||
|
uint8_t *payload, uint32_t payload_len)
|
||
|
DetectEngineThreadCtx *det_ctx,
|
||
|
Signature *s, SigMatch *sm,
|
||
|
uint8_t *payload, uint32_t payload_len)
|
||
|
{
|
||
|
SCEnter();
|
||
| ... | ... | |
|
ud->flags & DETECT_URICONTENT_WITHIN) {
|
||
|
SCLogDebug("det_ctx->uricontent_payload_offset %"PRIu32, det_ctx->uricontent_payload_offset);
|
||
|
offset = det_ctx->uricontent_payload_offset;
|
||
|
offset = det_ctx->payload_offset;
|
||
|
depth = payload_len;
|
||
|
if (ud->flags & DETECT_URICONTENT_DISTANCE) {
|
||
| ... | ... | |
|
}
|
||
|
if (ud->flags & DETECT_URICONTENT_WITHIN) {
|
||
|
if ((int32_t)depth > (int32_t)(det_ctx->uricontent_payload_offset + ud->within)) {
|
||
|
depth = det_ctx->uricontent_payload_offset + ud->within;
|
||
|
if ((int32_t)depth > (int32_t)(det_ctx->payload_offset + ud->within)) {
|
||
|
depth = det_ctx->payload_offset + ud->within;
|
||
|
}
|
||
|
SCLogDebug("ud->within %"PRIi32", det_ctx->uricontent_payload_offset %"PRIu32", depth %"PRIu32,
|
||
|
ud->within, det_ctx->uricontent_payload_offset, depth);
|
||
|
SCLogDebug("ud->within %"PRIi32", det_ctx->payload_offset %"PRIu32", depth %"PRIu32,
|
||
|
ud->within, det_ctx->payload_offset, depth);
|
||
|
}
|
||
|
if (ud->depth != 0) {
|
||
|
if ((ud->depth + det_ctx->uricontent_payload_offset) < depth) {
|
||
|
depth = det_ctx->uricontent_payload_offset + ud->depth;
|
||
|
if ((ud->depth + det_ctx->payload_offset) < depth) {
|
||
|
depth = det_ctx->payload_offset + ud->depth;
|
||
|
}
|
||
|
SCLogDebug("ud->depth %"PRIu32", depth %"PRIu32, ud->depth, depth);
|
||
| ... | ... | |
|
} else {
|
||
|
match_offset = (uint32_t)((found - payload) + ud->uricontent_len);
|
||
|
SCLogDebug("uricontent %"PRIu32" matched at offset %"PRIu32"", ud->id, match_offset);
|
||
|
det_ctx->uricontent_payload_offset = match_offset;
|
||
|
det_ctx->payload_offset = match_offset;
|
||
|
if (!(ud->flags & DETECT_URICONTENT_RELATIVE_NEXT)) {
|
||
|
SCLogDebug("no relative match coming up, so this is a match");
|
||
| ... | ... | |
|
}
|
||
|
} while(1);
|
||
|
} else if (sm->type == DETECT_PCRE) {
|
||
|
SCLogDebug("inspecting pcre");
|
||
|
int r = DetectPcrePayloadMatch(det_ctx, s, sm, /* no packet */NULL,
|
||
|
NULL, payload, payload_len);
|
||
|
if (r == 1) {
|
||
|
goto match;
|
||
|
}
|
||
|
SCReturnInt(0);
|
||
|
} else {
|
||
|
/* we should never get here, but bail out just in case */
|
||
|
BUG_ON(1);
|
||
| ... | ... | |
|
/* this sigmatch matched, inspect the next one. If it was the last,
|
||
|
* the payload portion of the signature matched. */
|
||
|
if (sm->next != NULL) {
|
||
|
int r = DoInspectPacketUri(de_ctx,det_ctx,s,sm->next, payload, payload_len);
|
||
|
int r = DoInspectPacketUri(de_ctx, det_ctx, s, sm->next, payload,
|
||
|
payload_len);
|
||
|
SCReturnInt(r);
|
||
|
} else {
|
||
|
SCReturnInt(1);
|
||
| ... | ... | |
|
int r = 0;
|
||
|
HtpState *htp_state = NULL;
|
||
|
if (!(det_ctx->sgh->flags & SIG_GROUP_HAVEURICONTENT)) {
|
||
|
SCLogDebug("no uricontent in sgh");
|
||
|
SCReturnInt(0);
|
||
|
}
|
||
|
htp_state = (HtpState *)alstate;
|
||
|
if (htp_state == NULL) {
|
||
|
SCLogDebug("no HTTP state");
|
||
| ... | ... | |
|
goto end;
|
||
|
}
|
||
|
det_ctx->de_have_httpuri = TRUE;
|
||
|
/* If we have the uricontent multi pattern matcher signatures in
|
||
|
signature list, then search the received HTTP uri(s) in the htp
|
||
|
state against those patterns */
|
||
| ... | ... | |
|
/* only consider uri sigs if we've seen at least one match */
|
||
|
/** \warning when we start supporting negated uri content matches
|
||
|
* we need to update this check as well */
|
||
|
if (cnt > 0) {
|
||
|
det_ctx->de_have_httpuri = TRUE;
|
||
|
if (cnt <= 0) {
|
||
|
det_ctx->de_have_httpuri = FALSE;
|
||
|
}
|
||
|
SCLogDebug("uricontent cnt %"PRIu32"", cnt);
|
||
| ... | ... | |
|
goto end;
|
||
|
}
|
||
|
if (det_ctx->de_mpm_scanned_uri == TRUE) {
|
||
|
if ((s->flags & SIG_FLAG_MPM_URI) && (det_ctx->de_mpm_scanned_uri == TRUE)) {
|
||
|
if (det_ctx->pmq.pattern_id_bitarray != NULL) {
|
||
|
/* filter out sigs that want pattern matches, but
|
||
|
* have no matches */
|
||
| ... | ... | |
|
sm = s->umatch;
|
||
|
det_ctx->uricontent_payload_offset = 0;
|
||
|
det_ctx->payload_offset = 0;
|
||
|
#ifdef DEBUG
|
||
|
DetectUricontentData *co = (DetectUricontentData *)sm->ctx;
|
||
| ... | ... | |
|
SCReturnInt(r);
|
||
|
}
|
||
|
/***********************************Unittests**********************************/
|
||
|
#ifdef UNITTESTS
|
||
|
static int UriTestSig01(void)
|
||
|
{
|
||
|
int result = 1;
|
||
|
Flow f;
|
||
|
HtpState *http_state = NULL;
|
||
|
uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
|
||
|
"User-Agent: Mozilla/1.0\r\n"
|
||
|
"Cookie: hellocatch\r\n\r\n";
|
||
|
uint32_t http_buf1_len = sizeof(http_buf1) - 1;
|
||
|
uint8_t http_buf2[] = "POST /oneself HTTP/1.0\r\n"
|
||
|
"User-Agent: Mozilla/1.0\r\n"
|
||
|
"Cookie: hellocatch\r\n\r\n";
|
||
|
uint32_t http_buf2_len = sizeof(http_buf2) - 1;
|
||
|
TcpSession ssn;
|
||
|
Packet p;
|
||
|
Signature *s = NULL;
|
||
|
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_buf1;
|
||
|
p.payload_len = http_buf1_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;
|
||
|
s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
|
||
|
"(msg:\"Test pcre U option\"; "
|
||
|
"uricontent:one; sid:1;)");
|
||
|
if (s == NULL) {
|
||
|
goto end;
|
||
|
}
|
||
|
SigGroupBuild(de_ctx);
|
||
|
DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
|
||
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_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;
|
||
|
}
|
||
|
r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf2, http_buf2_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;
|
||
|
}
|
||
|
if (!PacketAlertCheck(&p, 1)) {
|
||
|
printf("sig 1 alerted, but it should not: ");
|
||
|
goto end;
|
||
|
}
|
||
|
/* do detect */
|
||
|
SigMatchSignatures(&tv, de_ctx, det_ctx, &p);
|
||
|
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)
|
||
|
{
|
||
|
#ifdef UNITTESTS
|
||
|
UtRegisterTest("UriTestSig01", UriTestSig01, 1);
|
||
|
#endif /* UNITTESTS */
|
||
|
return;
|
||
|
}
|
||
| src/detect-engine-uri.h | ||
|---|---|---|
|
#ifndef __DETECT_ENGINE_URICONTENT_H__
|
||
|
#define __DETECT_ENGINE_URICONTENT_H__
|
||
|
int DetectEngineInspectPacketUris(DetectEngineCtx *,
|
||
|
DetectEngineThreadCtx *, Signature *, Flow *, uint8_t,
|
||
|
void *);
|
||
|
int DetectEngineInspectPacketUris(DetectEngineCtx *, DetectEngineThreadCtx *,
|
||
|
Signature *, Flow *, uint8_t, void *);
|
||
|
void UriRegisterTests(void);
|
||
|
#endif /* __DETECT_ENGINE_URICONTENT_H__ */
|
||
| src/detect-pcre.c | ||
|---|---|---|
|
AppLayerHtpEnableRequestBodyCallback();
|
||
|
SigMatchAppendAppLayer(s, sm);
|
||
|
} else if (pd->flags & DETECT_PCRE_URI) {
|
||
|
s->flags |= SIG_FLAG_APPLAYER;
|
||
|
if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) {
|
||
|
SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting"
|
||
|
" keywords.");
|
||
|
goto error;
|
||
|
}
|
||
|
s->alproto = ALPROTO_HTTP;
|
||
|
SigMatchAppendUricontent(s, sm);
|
||
|
} else {
|
||
|
switch (s->alproto) {
|
||
|
case ALPROTO_DCERPC:
|
||
| ... | ... | |
|
"Host: two.example.org\r\n"
|
||
|
"\r\n\r\n";
|
||
|
uint16_t buflen = strlen((char *)buf);
|
||
|
TcpSession ssn;
|
||
|
Packet p;
|
||
|
ThreadVars th_v;
|
||
|
DetectEngineThreadCtx *det_ctx;
|
||
| ... | ... | |
|
memset(&th_v, 0, sizeof(th_v));
|
||
|
memset(&p, 0, sizeof(p));
|
||
|
memset(&ssn, 0, sizeof(TcpSession));
|
||
|
FLOW_INITIALIZE(&f);
|
||
|
f.protoctx = (void *)&ssn;
|
||
|
f.src.family = AF_INET;
|
||
|
f.dst.family = AF_INET;
|
||
|
f.alproto = ALPROTO_HTTP;
|
||
|
p.src.family = AF_INET;
|
||
|
p.dst.family = AF_INET;
|
||
|
p.payload = buf;
|
||
|
p.payload_len = buflen;
|
||
|
p.proto = IPPROTO_TCP;
|
||
|
p.flow = &f;
|
||
|
p.flowflags |= FLOW_PKT_TOSERVER;
|
||
|
p.flowflags |= FLOW_PKT_ESTABLISHED;
|
||
|
StreamTcpInitConfig(TRUE);
|
||
|
FlowL7DataPtrInit(&f);
|
||
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
||
|
if (de_ctx == NULL) {
|
||
| ... | ... | |
|
SigGroupBuild(de_ctx);
|
||
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
||
|
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START, buf, buflen);
|
||
|
if (r != 0) {
|
||
|
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
||
|
result = 0;
|
||
|
goto end;
|
||
|
}
|
||
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
|
||
|
if (PacketAlertCheck(&p, 1) == 1) {
|
||
|
result = 1;
|
||
|
}
|
||
|
end:
|
||
|
SigGroupCleanup(de_ctx);
|
||
|
SigCleanSignatures(de_ctx);
|
||
|
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
|
||
|
DetectEngineCtxFree(de_ctx);
|
||
|
FlowL7DataPtrFree(&f);
|
||
|
StreamTcpFreeConfig(TRUE);
|
||
|
FLOW_DESTROY(&f);
|
||
|
end:
|
||
|
return result;
|
||
|
}
|
||
| src/suricata.c | ||
|---|---|---|
|
#include "detect-engine-sigorder.h"
|
||
|
#include "detect-engine-payload.h"
|
||
|
#include "detect-engine-dcepayload.h"
|
||
|
#include "detect-engine-uri.h"
|
||
|
#include "detect-engine-state.h"
|
||
|
#include "tm-queuehandlers.h"
|
||
| ... | ... | |
|
#endif
|
||
|
PayloadRegisterTests();
|
||
|
DcePayloadRegisterTests();
|
||
|
UriRegisterTests();
|
||
|
#ifdef PROFILING
|
||
|
SCProfilingRegisterTests();
|
||
|
#endif
|
||
- « Previous
- 1
- 2
- Next »