Project

General

Profile

Bug #220 ยป 0001-Adding-modifiers-C-H-and-M-to-pcre-http-cookie-heade.patch

Victor Julien, 08/30/2010 03:00 AM

View differences:

src/detect-http-header.c
/* flag the signature to indicate that we scan the app layer data */
s->flags |= SIG_FLAG_APPLAYER;
s->alproto = ALPROTO_HTTP;
/* enable http request body callback in the http app layer parser */
AppLayerHtpEnableRequestBodyCallback();
return 0;
src/detect-pcre.c
int DetectPcreMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *);
int DetectPcreALMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m);
int DetectPcreALMatchCookie(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m);
int DetectPcreALMatchHeader(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m);
int DetectPcreALMatchMethod(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m);
static int DetectPcreSetup (DetectEngineCtx *, Signature *, char *);
void DetectPcreFree(void *);
void DetectPcreRegisterTests(void);
......
sigmatch_table[DETECT_PCRE_HTTPBODY].Setup = NULL;
sigmatch_table[DETECT_PCRE_HTTPBODY].Free = DetectPcreFree;
sigmatch_table[DETECT_PCRE_HTTPBODY].RegisterTests = NULL;
sigmatch_table[DETECT_PCRE_HTTPBODY].flags |= SIGMATCH_PAYLOAD;
/* The same for Cookie, Method and Header */
sigmatch_table[DETECT_PCRE_HTTPCOOKIE].name = "__pcre_http_cookie__"; /* not a real keyword */
sigmatch_table[DETECT_PCRE_HTTPCOOKIE].Match = NULL;
sigmatch_table[DETECT_PCRE_HTTPCOOKIE].AppLayerMatch = DetectPcreALMatchCookie;
sigmatch_table[DETECT_PCRE_HTTPCOOKIE].alproto = ALPROTO_HTTP;
sigmatch_table[DETECT_PCRE_HTTPCOOKIE].Setup = NULL;
sigmatch_table[DETECT_PCRE_HTTPCOOKIE].Free = DetectPcreFree;
sigmatch_table[DETECT_PCRE_HTTPCOOKIE].RegisterTests = NULL;
sigmatch_table[DETECT_PCRE_HTTPCOOKIE].flags |= SIGMATCH_PAYLOAD;
sigmatch_table[DETECT_PCRE_HTTPMETHOD].name = "__pcre_http_method__"; /* not a real keyword */
sigmatch_table[DETECT_PCRE_HTTPMETHOD].Match = NULL;
sigmatch_table[DETECT_PCRE_HTTPMETHOD].AppLayerMatch = DetectPcreALMatchMethod;
sigmatch_table[DETECT_PCRE_HTTPMETHOD].alproto = ALPROTO_HTTP;
sigmatch_table[DETECT_PCRE_HTTPMETHOD].Setup = NULL;
sigmatch_table[DETECT_PCRE_HTTPMETHOD].Free = DetectPcreFree;
sigmatch_table[DETECT_PCRE_HTTPMETHOD].RegisterTests = NULL;
sigmatch_table[DETECT_PCRE_HTTPMETHOD].flags |= SIGMATCH_PAYLOAD;
sigmatch_table[DETECT_PCRE_HTTPHEADER].name = "__pcre_http_header__"; /* not a real keyword */
sigmatch_table[DETECT_PCRE_HTTPHEADER].Match = NULL;
sigmatch_table[DETECT_PCRE_HTTPHEADER].AppLayerMatch = DetectPcreALMatchHeader;
sigmatch_table[DETECT_PCRE_HTTPHEADER].alproto = ALPROTO_HTTP;
sigmatch_table[DETECT_PCRE_HTTPHEADER].Setup = NULL;
sigmatch_table[DETECT_PCRE_HTTPHEADER].Free = DetectPcreFree;
sigmatch_table[DETECT_PCRE_HTTPHEADER].RegisterTests = NULL;
sigmatch_table[DETECT_PCRE_HTTPHEADER].flags |= SIGMATCH_PAYLOAD;
const char *eb;
int eo;
int opts = 0;
......
return;
}
/**
* \brief Match a regex on data sent at an http method (needs the l7 parser).
*
* \param det_ctx Thread detection ctx.
* \param s Signature.
* \param sm SigMatch to match against.
* \param data Data to match against.
* \param data_len Data length.
*
* \retval 1: match
* \retval 0: no match
*/
int DetectPcreALDoMatchMethod(DetectEngineThreadCtx *det_ctx, Signature *s,
SigMatch *m, Flow *f, uint8_t flags,
void *state)
{
SCEnter();
int ret = 0;
int toret = 0;
size_t idx;
#define MAX_SUBSTRINGS 30
int ov[MAX_SUBSTRINGS];
uint8_t *ptr = NULL;
uint16_t len = 0;
DetectPcreData *pe = (DetectPcreData *)m->ctx;
/* define ptr & len */
SCMutexLock(&f->m);
SCLogDebug("got lock %p", &f->m);
HtpState *htp_state = (HtpState *)state;
if (htp_state == NULL) {
SCLogDebug("no HTTP layer state has been received, so no match");
goto end;
}
if (!(htp_state->flags & HTP_FLAG_STATE_OPEN)) {
SCLogDebug("HTP state not yet properly setup, so no match");
goto end;
}
SCLogDebug("htp_state %p, flow %p", htp_state, f);
SCLogDebug("htp_state->connp %p", htp_state->connp);
SCLogDebug("htp_state->connp->conn %p", htp_state->connp->conn);
if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
SCLogDebug("HTTP connection structure is NULL");
goto end;
}
htp_tx_t *tx = NULL;
for (idx = 0;//htp_state->new_in_tx_index;
idx < list_size(htp_state->connp->conn->transactions); idx++)
{
tx = list_get(htp_state->connp->conn->transactions, idx);
if (tx == NULL)
continue;
ptr = (uint8_t *) bstr_ptr(tx->request_method);
len = bstr_size(tx->request_method);
if (ptr == NULL)
continue;
//printf("Matching Method");
//PrintRawUriFp(stdout, (uint8_t*)ptr, len);
/* run the actual pcre detection */
ret = pcre_exec(pe->re, pe->sd, (char *)ptr, len, 0, 0, ov, MAX_SUBSTRINGS);
SCLogDebug("ret %d (negating %s)", ret, pe->negate ? "set" : "not set");
if (ret == PCRE_ERROR_NOMATCH) {
if (pe->negate == 1) {
/* regex didn't match with negate option means we
* consider it a match */
ret = 1;
toret |= ret;
break;
} else {
ret = 0;
}
toret |= ret;
} else if (ret >= 0) {
if (pe->negate == 1) {
/* regex matched but we're negated, so not
* considering it a match */
ret = 0;
} else {
/* regex matched and we're not negated,
* considering it a match */
ret = 1;
toret |= ret;
break;
}
} else {
SCLogDebug("pcre had matching error");
ret = 0;
}
}
end:
SCMutexUnlock(&f->m);
SCLogDebug("released lock %p", &f->m);
SCReturnInt(toret);
}
/**
* \brief Match a regex on data sent at an http header (needs the l7 parser).
*
* \param det_ctx Thread detection ctx.
* \param s Signature.
* \param sm SigMatch to match against.
* \param data Data to match against.
* \param data_len Data length.
*
* \retval 1: match
* \retval 0: no match
*/
int DetectPcreALDoMatchHeader(DetectEngineThreadCtx *det_ctx, Signature *s,
SigMatch *m, Flow *f, uint8_t flags,
void *state)
{
SCEnter();
int ret = 0;
int toret = 0;
size_t idx;
#define MAX_SUBSTRINGS 30
int ov[MAX_SUBSTRINGS];
uint8_t *ptr = NULL;
uint16_t len = 0;
DetectPcreData *pe = (DetectPcreData *)m->ctx;
/* define ptr & len */
SCMutexLock(&f->m);
SCLogDebug("got lock %p", &f->m);
HtpState *htp_state = (HtpState *)state;
if (htp_state == NULL) {
SCLogDebug("no HTTP layer state has been received, so no match");
goto end;
}
if (!(htp_state->flags & HTP_FLAG_STATE_OPEN)) {
SCLogDebug("HTP state not yet properly setup, so no match");
goto end;
}
SCLogDebug("htp_state %p, flow %p", htp_state, f);
SCLogDebug("htp_state->connp %p", htp_state->connp);
SCLogDebug("htp_state->connp->conn %p", htp_state->connp->conn);
if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
SCLogDebug("HTTP connection structure is NULL");
goto end;
}
htp_tx_t *tx = NULL;
bstr *headers = NULL;
for (idx = 0;//htp_state->new_in_tx_index;
idx < list_size(htp_state->connp->conn->transactions); idx++)
{
tx = list_get(htp_state->connp->conn->transactions, idx);
if (tx == NULL)
continue;
SCLogDebug("inspecting tx %p", tx);
headers = htp_tx_get_request_headers_raw(tx);
if (headers == NULL)
continue;
ptr = (uint8_t *)bstr_ptr(headers);
len = bstr_len(headers);
if (ptr == NULL)
continue;
//printf("Matching Header");
//PrintRawUriFp(stdout, (uint8_t*)ptr, len);
/* run the actual pcre detection */
ret = pcre_exec(pe->re, pe->sd, (char *)ptr, len, 0, 0, ov, MAX_SUBSTRINGS);
SCLogDebug("ret %d (negating %s)", ret, pe->negate ? "set" : "not set");
if (ret == PCRE_ERROR_NOMATCH) {
if (pe->negate == 1) {
/* regex didn't match with negate option means we
* consider it a match */
ret = 1;
toret |= ret;
break;
} else {
ret = 0;
}
toret |= ret;
} else if (ret >= 0) {
if (pe->negate == 1) {
/* regex matched but we're negated, so not
* considering it a match */
ret = 0;
} else {
/* regex matched and we're not negated,
* considering it a match */
ret = 1;
toret |= ret;
break;
}
} else {
SCLogDebug("pcre had matching error");
ret = 0;
}
}
end:
SCMutexUnlock(&f->m);
SCLogDebug("released lock %p", &f->m);
SCReturnInt(toret);
}
/**
* \brief Match a regex on data sent at an http cookie (needs the l7 parser).
*
* \param det_ctx Thread detection ctx.
* \param s Signature.
* \param sm SigMatch to match against.
* \param data Data to match against.
* \param data_len Data length.
*
* \retval 1: match
* \retval 0: no match
*/
int DetectPcreALDoMatchCookie(DetectEngineThreadCtx *det_ctx, Signature *s,
SigMatch *m, Flow *f, uint8_t flags,
void *state)
{
SCEnter();
int ret = 0;
int toret = 0;
size_t idx;
#define MAX_SUBSTRINGS 30
int ov[MAX_SUBSTRINGS];
uint8_t *ptr = NULL;
uint16_t len = 0;
DetectPcreData *pe = (DetectPcreData *)m->ctx;
/* define ptr & len */
SCMutexLock(&f->m);
SCLogDebug("got lock %p", &f->m);
HtpState *htp_state = (HtpState *)state;
if (htp_state == NULL) {
SCLogDebug("no HTTP layer state has been received, so no match");
goto end;
}
if (!(htp_state->flags & HTP_FLAG_STATE_OPEN)) {
SCLogDebug("HTP state not yet properly setup, so no match");
goto end;
}
SCLogDebug("htp_state %p, flow %p", htp_state, f);
SCLogDebug("htp_state->connp %p", htp_state->connp);
SCLogDebug("htp_state->connp->conn %p", htp_state->connp->conn);
if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
SCLogDebug("HTTP connection structure is NULL");
goto end;
}
htp_tx_t *tx = NULL;
for (idx = 0;//htp_state->new_in_tx_index;
idx < list_size(htp_state->connp->conn->transactions); idx++)
{
tx = list_get(htp_state->connp->conn->transactions, idx);
if (tx == NULL)
continue;
htp_header_t *h = NULL;
h = (htp_header_t *) table_getc(tx->request_headers, "Cookie");
if (h == NULL) {
SCLogDebug("no HTTP Cookie header in the received request");
goto end;
}
ptr = (uint8_t *) bstr_ptr(h->value);
len = bstr_size(h->value);
if (ptr == NULL)
continue;
//printf("Matching Cookie");
//PrintRawUriFp(stdout, (uint8_t*)ptr, len);
SCLogDebug("we have a cookie header");
/* run the actual pcre detection */
ret = pcre_exec(pe->re, pe->sd, (char *)ptr, len, 0, 0, ov, MAX_SUBSTRINGS);
SCLogDebug("ret %d (negating %s)", ret, pe->negate ? "set" : "not set");
if (ret == PCRE_ERROR_NOMATCH) {
if (pe->negate == 1) {
/* regex didn't match with negate option means we
* consider it a match */
ret = 1;
toret |= ret;
break;
} else {
ret = 0;
}
toret |= ret;
} else if (ret >= 0) {
if (pe->negate == 1) {
/* regex matched but we're negated, so not
* considering it a match */
ret = 0;
} else {
/* regex matched and we're not negated,
* considering it a match */
ret = 1;
toret |= ret;
break;
}
} else {
SCLogDebug("pcre had matching error");
if (pe->negate == 1) {
ret = 1;
toret |= ret;
break;
} else {
ret = 0;
}
toret |= ret;
}
}
end:
SCMutexUnlock(&f->m);
SCLogDebug("released lock %p", &f->m);
SCReturnInt(toret);
}
int DetectPcreALDoMatch(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch *m, Flow *f, uint8_t flags, void *state) {
#define MAX_SUBSTRINGS 30
SCEnter();
......
}
/**
* \brief match the specified pcre at http header, requesting it from htp/L7
*
* \param t pointer to thread vars
* \param det_ctx pointer to the pattern matcher thread
* \param p pointer to the current packet
* \param m pointer to the sigmatch that we will cast into DetectPcreData
*
* \retval int 0 no match; 1 match
*/
int DetectPcreALMatchHeader(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
uint8_t flags, void *state, Signature *s, SigMatch *m)
{
int r = DetectPcreALDoMatchHeader(det_ctx, s, m, f, flags, state);
SCReturnInt(r);
}
/**
* \brief match the specified pcre at http method, requesting it from htp/L7
*
* \param t pointer to thread vars
* \param det_ctx pointer to the pattern matcher thread
* \param p pointer to the current packet
* \param m pointer to the sigmatch that we will cast into DetectPcreData
*
* \retval int 0 no match; 1 match
*/
int DetectPcreALMatchMethod(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
uint8_t flags, void *state, Signature *s, SigMatch *m)
{
int r = DetectPcreALDoMatchMethod(det_ctx, s, m, f, flags, state);
SCReturnInt(r);
}
/**
* \brief match the specified pcre at http cookie, requesting it from htp/L7
*
* \param t pointer to thread vars
* \param det_ctx pointer to the pattern matcher thread
* \param p pointer to the current packet
* \param m pointer to the sigmatch that we will cast into DetectPcreData
*
* \retval int 0 no match; 1 match
*/
int DetectPcreALMatchCookie(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
uint8_t flags, void *state, Signature *s, SigMatch *m)
{
int r = DetectPcreALDoMatchCookie(det_ctx, s, m, f, flags, state);
SCReturnInt(r);
}
/**
* \brief Match a regex on a single payload.
*
* \param det_ctx Thread detection ctx.
......
case 'U': /* snort's option */
pd->flags |= DETECT_PCRE_URI;
break;
case 'H': /* snort's option */
pd->flags |= DETECT_PCRE_HEADER;
break;
case 'M': /* snort's option */
pd->flags |= DETECT_PCRE_METHOD;
break;
case 'C': /* snort's option */
pd->flags |= DETECT_PCRE_COOKIE;
break;
case 'O':
pd->flags |= DETECT_PCRE_MATCH_LIMIT;
break;
......
switch (s->alproto) {
case ALPROTO_DCERPC:
if ( (pd->flags & DETECT_PCRE_URI) ||
(pd->flags & DETECT_PCRE_METHOD) ||
(pd->flags & DETECT_PCRE_HEADER) ||
(pd->flags & DETECT_PCRE_COOKIE) ||
(pd->flags & DETECT_PCRE_HTTP_BODY_AL) ) {
SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "Invalid option. "
"DCERPC rule has pcre keyword with http related modifier.");
......
sm->type = DETECT_PCRE;
sm->ctx = (void *)pd;
if (pd->flags & DETECT_PCRE_HTTP_BODY_AL) {
if (pd->flags & DETECT_PCRE_HEADER) {
sm->type = DETECT_PCRE_HTTPHEADER;
SCLogDebug("Header inspection modifier set");
s->flags |= SIG_FLAG_APPLAYER;
SigMatchAppendAppLayer(s, sm);
} else if (pd->flags & DETECT_PCRE_COOKIE) {
sm->type = DETECT_PCRE_HTTPCOOKIE;
SCLogDebug("Cookie inspection modifier set");
s->flags |= SIG_FLAG_APPLAYER;
SigMatchAppendAppLayer(s, sm);
} else if (pd->flags & DETECT_PCRE_METHOD) {
sm->type = DETECT_PCRE_HTTPMETHOD;
SCLogDebug("Method inspection modifier set");
s->flags |= SIG_FLAG_APPLAYER;
SigMatchAppendAppLayer(s, sm);
} else if (pd->flags & DETECT_PCRE_HTTP_BODY_AL) {
sm->type = DETECT_PCRE_HTTPBODY;
SCLogDebug("Body inspection modifier set");
......
return result;
}
/** \test Check the signature working to alert when cookie modifier is
* passed to pcre
*/
static int DetectPcreTestSig09(void) {
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
"Cookie: dummy\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, 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->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP cookie\"; pcre:\"/dummy/C\"; "
" sid:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1);
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(&th_v, de_ctx, det_ctx, p);
if (!PacketAlertCheck(p, 1)) {
printf("sig 1 failed to match: ");
goto end;
}
result = 1;
end:
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
DetectEngineCtxFree(de_ctx);
}
FlowL7DataPtrFree(&f);
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when cookie modifier is
* passed to a negated pcre
*/
static int DetectPcreTestSig10(void) {
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
"Cookie: dummoOOooooO\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, 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->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP cookie\"; pcre:!\"/dummy/C\"; "
" sid:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1);
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(&th_v, de_ctx, det_ctx, p);
if (!PacketAlertCheck(p, 1)) {
printf("sig 1 should match: ");
goto end;
}
result = 1;
end:
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
DetectEngineCtxFree(de_ctx);
}
FlowL7DataPtrFree(&f);
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when method modifier is
* passed to pcre
*/
static int DetectPcreTestSig11(void) {
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
"Cookie: dummy\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, 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->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP method\"; pcre:\"/POST/M\"; "
" sid:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1);
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(&th_v, de_ctx, det_ctx, p);
if (!PacketAlertCheck(p, 1)) {
printf("sig 1 failed to match: ");
goto end;
}
result = 1;
end:
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
DetectEngineCtxFree(de_ctx);
}
FlowL7DataPtrFree(&f);
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when method modifier is
* passed to a negated pcre
*/
static int DetectPcreTestSig12(void) {
int result = 0;
Flow f;
uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
"Cookie: dummoOOooooO\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, 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->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP method\"; pcre:!\"/POST/M\"; "
" sid:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1);
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(&th_v, de_ctx, det_ctx, p);
if (!PacketAlertCheck(p, 1)) {
printf("sig 1 should match: ");
goto end;
}
result = 1;
end:
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
DetectEngineCtxFree(de_ctx);
}
FlowL7DataPtrFree(&f);
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when header modifier is
* passed to pcre
*/
static int DetectPcreTestSig13(void) {
int result = 0;
Flow f;
uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
"Cookie: dummy\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, 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->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP header\"; pcre:\"/User[-_]Agent[:]?\\sMozilla/H\"; "
" sid:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1);
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(&th_v, de_ctx, det_ctx, p);
if (!PacketAlertCheck(p, 1)) {
printf("sig 1 failed to match: ");
goto end;
}
result = 1;
end:
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
DetectEngineCtxFree(de_ctx);
}
FlowL7DataPtrFree(&f);
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
/** \test Check the signature working to alert when header modifier is
* passed to a negated pcre
*/
static int DetectPcreTestSig14(void) {
int result = 0;
Flow f;
uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nUser-Agent: IEXPLORER/1.0\r\n"
"Cookie: dummoOOooooO\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
TcpSession ssn;
Packet *p = NULL;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
HtpState *http_state = NULL;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p = UTHBuildPacket(NULL, 0, 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->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
"\"HTTP header\"; pcre:!\"/User-Agent[:]?\\s+Mozilla/H\"; "
" sid:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_HTTP, STREAM_TOSERVER, httpbuf1, httplen1);
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(&th_v, de_ctx, det_ctx, p);
if (!PacketAlertCheck(p, 1)) {
printf("sig 1 should match: ");
goto end;
}
result = 1;
end:
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
DetectEngineCtxFree(de_ctx);
}
FlowL7DataPtrFree(&f);
StreamTcpFreeConfig(TRUE);
UTHFreePackets(&p, 1);
return result;
}
#endif /* UNITTESTS */
/**
......
UtRegisterTest("DetectPcreTestSig06", DetectPcreTestSig06, 1);
UtRegisterTest("DetectPcreTestSig07 -- anchored pcre", DetectPcreTestSig07, 1);
UtRegisterTest("DetectPcreTestSig08 -- anchored pcre", DetectPcreTestSig08, 1);
UtRegisterTest("DetectPcreTestSig09 -- Cookie modifier", DetectPcreTestSig09, 1);
UtRegisterTest("DetectPcreTestSig10 -- negated Cookie modifier", DetectPcreTestSig10, 1);
UtRegisterTest("DetectPcreTestSig11 -- Method modifier", DetectPcreTestSig11, 1);
UtRegisterTest("DetectPcreTestSig12 -- negated Method modifier", DetectPcreTestSig12, 1);
UtRegisterTest("DetectPcreTestSig13 -- Header modifier", DetectPcreTestSig13, 1);
UtRegisterTest("DetectPcreTestSig14 -- negated Header modifier", DetectPcreTestSig14, 1);
#endif /* UNITTESTS */
}
src/detect-pcre.h
#ifndef __DETECT_PCRE_H__
#define __DETECT_PCRE_H__
#define DETECT_PCRE_RELATIVE 0x01
#define DETECT_PCRE_RAWBYTES 0x02
#define DETECT_PCRE_URI 0x04
#define DETECT_PCRE_RELATIVE 0x0001
#define DETECT_PCRE_RAWBYTES 0x0002
#define DETECT_PCRE_URI 0x0004
#define DETECT_PCRE_CAPTURE_PKT 0x08
#define DETECT_PCRE_CAPTURE_FLOW 0x10
#define DETECT_PCRE_MATCH_LIMIT 0x20
#define DETECT_PCRE_CAPTURE_PKT 0x0008
#define DETECT_PCRE_CAPTURE_FLOW 0x0010
#define DETECT_PCRE_MATCH_LIMIT 0x0020
#define DETECT_PCRE_HTTP_BODY_AL 0x40
#define DETECT_PCRE_RELATIVE_NEXT 0x80
#define DETECT_PCRE_HTTP_BODY_AL 0x0040
#define DETECT_PCRE_RELATIVE_NEXT 0x0080
/* new modifiers 2.8.5.3 support */
#define DETECT_PCRE_HEADER 0x0100
#define DETECT_PCRE_COOKIE 0x0200
#define DETECT_PCRE_METHOD 0x0400
typedef struct DetectPcreData_ {
/* pcre options */
......
pcre_extra *sd;
int opts;
uint8_t flags;
uint16_t flags;
uint8_t negate;
char *capname;
src/detect.h
DETECT_URICONTENT,
DETECT_PCRE,
DETECT_PCRE_HTTPBODY,
DETECT_PCRE_HTTPCOOKIE,
DETECT_PCRE_HTTPHEADER,
DETECT_PCRE_HTTPMETHOD,
DETECT_ACK,
DETECT_SEQ,
DETECT_DEPTH,
    (1-1/1)