app-layer: template for application layer content inspection

pull/1634/head
Jason Ish 10 years ago
parent bcda92134d
commit 06beca62f5

@ -123,6 +123,7 @@ detect-engine-siggroup.c detect-engine-siggroup.h \
detect-engine-sigorder.c detect-engine-sigorder.h \
detect-engine-state.c detect-engine-state.h \
detect-engine-tag.c detect-engine-tag.h \
detect-engine-template.c detect-engine-template.h \
detect-engine-threshold.c detect-engine-threshold.h \
detect-engine-uri.c detect-engine-uri.h \
detect-fast-pattern.c detect-fast-pattern.h \
@ -195,6 +196,7 @@ detect-ssl-version.c detect-ssl-version.h \
detect-stream_size.c detect-stream_size.h \
detect-tag.c detect-tag.h \
detect-template.c detect-template.h \
detect-template-buffer.c detect-template-buffer.h \
detect-threshold.c detect-threshold.h \
detect-tls.c detect-tls.h \
detect-tls-version.c detect-tls-version.h \

@ -50,6 +50,7 @@ enum {
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HRHHD,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_DNSQUERY,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_FD_SMTP,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_TEMPLATE_BUFFER,
};
int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,

@ -81,6 +81,7 @@
#define DE_STATE_FLAG_FD_SMTP_INSPECT (1 << 21)
#define DE_STATE_FLAG_DNSREQUEST_INSPECT (1 << 22)
#define DE_STATE_FLAG_DNSRESPONSE_INSPECT (1 << 23)
#define DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT (1 << 24)
/* state flags */
#define DETECT_ENGINE_STATE_FLAG_FILE_STORE_DISABLED 0x0001

@ -0,0 +1,46 @@
/* Copyright (C) 2015 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "suricata-common.h"
#include "stream.h"
#include "detect-engine-content-inspection.h"
#include "app-layer-template.h"
int DetectEngineInspectTemplateBuffer(ThreadVars *tv, DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, Signature *s, Flow *f, uint8_t flags,
void *alstate, void *txv, uint64_t tx_id)
{
TemplateTransaction *tx = (TemplateTransaction *)txv;
int ret = 0;
if (flags & STREAM_TOSERVER && tx->request_buffer != NULL) {
ret = DetectEngineContentInspection(de_ctx, det_ctx, s,
s->sm_lists[DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH], f,
tx->request_buffer, tx->request_buffer_len, 0,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_TEMPLATE_BUFFER, NULL);
}
else if (flags & STREAM_TOCLIENT && tx->response_buffer != NULL) {
ret = DetectEngineContentInspection(de_ctx, det_ctx, s,
s->sm_lists[DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH], f,
tx->response_buffer, tx->response_buffer_len, 0,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_TEMPLATE_BUFFER, NULL);
}
SCLogNotice("Returning %d.", ret);
return ret;
}

@ -0,0 +1,25 @@
/* Copyright (C) 2015 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __DETECT_TEMPLATE_ENGINE_H__
#define __DETECT_TEMPLATE_ENGINE_H__
int DetectEngineInspectTemplateBuffer(ThreadVars *, DetectEngineCtx *,
DetectEngineThreadCtx *, Signature *, Flow *, uint8_t, void *, void *,
uint64_t);
#endif /* __DETECT_TEMPLATE_ENGINE_H__ */

@ -62,6 +62,7 @@
#include "detect-engine-dns.h"
#include "detect-engine-modbus.h"
#include "detect-engine-filedata-smtp.h"
#include "detect-engine-template.h"
#include "detect-engine.h"
#include "detect-engine-state.h"
@ -285,6 +286,13 @@ void DetectEngineRegisterAppInspectionEngines(void)
DE_STATE_FLAG_FD_SMTP_INSPECT,
0,
DetectEngineInspectSMTPFiledata },
/* Template. */
{ IPPROTO_TCP,
ALPROTO_TEMPLATE,
DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH,
DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT,
0,
DetectEngineInspectTemplateBuffer },
};
struct tmp_t data_toclient[] = {
@ -352,6 +360,13 @@ void DetectEngineRegisterAppInspectionEngines(void)
DE_STATE_FLAG_DNSRESPONSE_INSPECT,
1,
DetectEngineInspectDnsResponse },
/* Template. */
{ IPPROTO_TCP,
ALPROTO_TEMPLATE,
DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH,
DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT,
1,
DetectEngineInspectTemplateBuffer },
};
size_t i;
@ -2630,6 +2645,9 @@ const char *DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
case DETECT_SM_LIST_MODBUS_MATCH:
return "modbus";
case DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH:
return "template_buffer";
case DETECT_SM_LIST_POSTMATCH:
return "post-match";

@ -1479,6 +1479,11 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr,
if (sig->sm_lists[DETECT_SM_LIST_HRHHDMATCH])
sig->flags |= SIG_FLAG_STATE_MATCH;
/* Template. */
if (sig->sm_lists[DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH]) {
sig->flags |= SIG_FLAG_STATE_MATCH;
}
/* DNS */
if (sig->sm_lists[DETECT_SM_LIST_DNSQUERYNAME_MATCH])
sig->flags |= SIG_FLAG_STATE_MATCH;

@ -0,0 +1,165 @@
/* Copyright (C) 2015 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file Set up of the "template_buffer" keyword to allow content inspections
* on the decoded template application layer buffers.
*/
#include "suricata-common.h"
#include "detect.h"
#include "app-layer-template.h"
static int DetectTemplateBufferSetup(DetectEngineCtx *, Signature *, char *);
static void DetectTemplateBufferRegisterTests(void);
void DetectTemplateBufferRegister(void)
{
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].name = "template_buffer";
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].desc =
"Template content modififier to match on the template buffers";
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].alproto = ALPROTO_TEMPLATE;
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].Setup = DetectTemplateBufferSetup;
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].RegisterTests =
DetectTemplateBufferRegisterTests;
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].flags |= SIGMATCH_PAYLOAD;
SCLogNotice("Template application layer detect registered.");
}
static int DetectTemplateBufferSetup(DetectEngineCtx *de_ctx, Signature *s,
char *str)
{
s->list = DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH;
s->alproto = ALPROTO_TEMPLATE;
return 0;
}
#ifdef UNITTESTS
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include "app-layer-parser.h"
#include "detect-engine.h"
#include "detect-parse.h"
#include "flow-util.h"
#include "stream-tcp.h"
static int DetectTemplateBufferTest(void)
{
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
DetectEngineThreadCtx *det_ctx = NULL;
DetectEngineCtx *de_ctx = NULL;
Flow f;
Packet *p;
TcpSession tcp;
ThreadVars tv;
Signature *s;
int result = 0;
uint8_t request[] = "Hello World!";
/* Setup flow. */
memset(&f, 0, sizeof(Flow));
memset(&tcp, 0, sizeof(TcpSession));
memset(&tv, 0, sizeof(ThreadVars));
p = UTHBuildPacket(request, sizeof(request), IPPROTO_TCP);
FLOW_INITIALIZE(&f);
f.alproto = ALPROTO_TEMPLATE;
f.protoctx = (void *)&tcp;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
p->flow = &f;
p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
StreamTcpInitConfig(TRUE);
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
/* This rule should match. */
s = DetectEngineAppendSig(de_ctx,
"alert tcp any any -> any any ("
"msg:\"TEMPLATE Test Rule\"; "
"template_buffer; content:\"World!\"; "
"sid:1; rev:1;)");
if (s == NULL) {
goto end;
}
/* This rule should not match. */
s = DetectEngineAppendSig(de_ctx,
"alert tcp any any -> any any ("
"msg:\"TEMPLATE Test Rule\"; "
"template_buffer; content:\"W0rld!\"; "
"sid:2; rev:1;)");
if (s == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
SCMutexLock(&f.m);
AppLayerParserParse(alp_tctx, &f, ALPROTO_TEMPLATE, STREAM_TOSERVER,
request, sizeof(request));
SCMutexUnlock(&f.m);
/* Check that we have app-layer state. */
if (f.alstate == NULL) {
goto end;
}
SigMatchSignatures(&tv, de_ctx, det_ctx, p);
if (!PacketAlertCheck(p, 1)) {
goto end;
}
if (PacketAlertCheck(p, 2)) {
goto end;
}
result = 1;
end:
/* Cleanup. */
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
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);
UTHFreePacket(p);
return result;
}
#endif
static void DetectTemplateBufferRegisterTests(void)
{
#ifdef UNITTESTS
UtRegisterTest("DetectTemplateBufferTest", DetectTemplateBufferTest, 1);
#endif /* UNITTESTS */
}

@ -0,0 +1,25 @@
/* Copyright (C) 2015 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __DETECT_TEMPLATE_BUFFER_H__
#define __DETECT_TEMPLATE_BUFFER_H__
#include "app-layer-template.h"
void DetectTemplateBufferRegister(void);
#endif /* __DETECT_TEMPLATE_BUFFER_H__ */

@ -156,6 +156,7 @@
#include "detect-dns-query.h"
#include "detect-app-layer-protocol.h"
#include "detect-template.h"
#include "detect-template-buffer.h"
#include "util-rule-vars.h"
@ -163,6 +164,7 @@
#include "app-layer-protos.h"
#include "app-layer-htp.h"
#include "app-layer-smtp.h"
#include "app-layer-template.h"
#include "detect-tls.h"
#include "detect-tls-version.h"
#include "detect-ssh-proto-version.h"
@ -2431,6 +2433,10 @@ PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto, int has_state
SCLogDebug("packet/flow has smtp state");
(*mask) |= SIG_MASK_REQUIRE_SMTP_STATE;
break;
case ALPROTO_TEMPLATE:
SCLogDebug("packet/flow has template state");
(*mask) |= SIG_MASK_REQUIRE_TEMPLATE_STATE;
break;
default:
SCLogDebug("packet/flow has other state");
break;
@ -2668,6 +2674,10 @@ static int SignatureCreateMask(Signature *s)
s->mask |= SIG_MASK_REQUIRE_SMTP_STATE;
SCLogDebug("sig requires smtp state");
}
if (s->alproto == ALPROTO_TEMPLATE) {
s->mask |= SIG_MASK_REQUIRE_TEMPLATE_STATE;
SCLogDebug("sig requires template state");
}
if ((s->mask & SIG_MASK_REQUIRE_DCE_STATE) ||
(s->mask & SIG_MASK_REQUIRE_HTTP_STATE) ||
@ -2675,6 +2685,7 @@ static int SignatureCreateMask(Signature *s)
(s->mask & SIG_MASK_REQUIRE_DNS_STATE) ||
(s->mask & SIG_MASK_REQUIRE_FTP_STATE) ||
(s->mask & SIG_MASK_REQUIRE_SMTP_STATE) ||
(s->mask & SIG_MASK_REQUIRE_TEMPLATE_STATE) ||
(s->mask & SIG_MASK_REQUIRE_TLS_STATE))
{
s->mask |= SIG_MASK_REQUIRE_FLOW;
@ -5238,6 +5249,7 @@ void SigTableSetup(void)
DetectModbusRegister();
DetectAppLayerProtocolRegister();
DetectTemplateRegister();
DetectTemplateBufferRegister();
}
void SigTableRegisterTests(void)

@ -126,6 +126,8 @@ enum DetectSigmatchListEnum {
DETECT_SM_LIST_MODBUS_MATCH,
DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH,
/* list for post match actions: flowbit set, flowint increment, etc */
DETECT_SM_LIST_POSTMATCH,
@ -305,6 +307,7 @@ typedef struct DetectPort_ {
#define SIG_MASK_REQUIRE_DNS_STATE (1<<10)
#define SIG_MASK_REQUIRE_FTP_STATE (1<<11)
#define SIG_MASK_REQUIRE_SMTP_STATE (1<<12)
#define SIG_MASK_REQUIRE_TEMPLATE_STATE (1<<13)
/* for now a uint8_t is enough */
#define SignatureMask uint16_t
@ -1229,6 +1232,7 @@ enum {
DETECT_XBITS,
DETECT_TEMPLATE,
DETECT_AL_TEMPLATE_BUFFER,
/* make sure this stays last */
DETECT_TBLSIZE,

Loading…
Cancel
Save