Add krb5_cname and krb5_sname detection keywords

pull/3391/head
Pierre Chifflier 8 years ago
parent 0bd81ff838
commit d6b9c0294a

@ -23,3 +23,48 @@ Syntax::
Signature example::
alert krb5 any any -> any any (msg:"Kerberos 5 AS-REQ message"; krb5_msg_type:10; sid:3; rev:1;)
krb5_cname
----------
Kerberos client name, provided in the ticket (for AS-REQ and TGS-REQ messages).
If the client name from the Kerberos message is composed of several parts, the
name is compared to each part and the match will succeed if any is identical.
Comparison is case-sensitive.
Syntax::
krb5_cname:[!]<name>
Signature example::
alert krb5 any any -> any any (msg:"Kerberos 5 des server name"; krb5_cname; content:"des"; sid:4; rev:1;)
``krb5_cname`` is a 'sticky buffer'.
``krb5_cname`` can be used as ``fast_pattern``.
krb5_sname
----------
Kerberos server name, provided in the ticket (for AS-REQ and TGS-REQ messages)
or in the error message.
If the server name from the Kerberos message is composed of several parts, the
name is compared to each part and the match will succeed if any is identical.
Comparison is case-sensitive.
Syntax::
krb5_sname:[!]<name>
Signature example::
alert krb5 any any -> any any (msg:"Kerberos 5 krbtgt server name"; krb5_sname; content:"krbtgt"; sid:5; rev:1;)
``krb5_sname`` is a 'sticky buffer'.
``krb5_sname`` can be used as ``fast_pattern``.

@ -27,3 +27,39 @@ pub unsafe extern "C" fn rs_krb5_tx_get_msgtype(tx: &mut KRB5Transaction,
{
*ptr = tx.msg_type.0;
}
#[no_mangle]
pub unsafe extern "C" fn rs_krb5_tx_get_cname(tx: &mut KRB5Transaction,
i: libc::uint16_t,
buffer: *mut *const libc::uint8_t,
buffer_len: *mut libc::uint32_t)
-> libc::uint8_t
{
if let Some(ref s) = tx.cname {
if (i as usize) < s.name_string.len() {
let value = &s.name_string[i as usize];
*buffer = value.as_ptr();
*buffer_len = value.len() as u32;
return 1;
}
}
0
}
#[no_mangle]
pub unsafe extern "C" fn rs_krb5_tx_get_sname(tx: &mut KRB5Transaction,
i: libc::uint16_t,
buffer: *mut *const libc::uint8_t,
buffer_len: *mut libc::uint32_t)
-> libc::uint8_t
{
if let Some(ref s) = tx.sname {
if (i as usize) < s.name_string.len() {
let value = &s.name_string[i as usize];
*buffer = value.as_ptr();
*buffer_len = value.len() as u32;
return 1;
}
}
0
}

@ -213,7 +213,9 @@ detect-ipproto.c detect-ipproto.h \
detect-iprep.c detect-iprep.h \
detect-isdataat.c detect-isdataat.h \
detect-itype.c detect-itype.h \
detect-krb5-cname.c detect-krb5-cname.h \
detect-krb5-msgtype.c detect-krb5-msgtype.h \
detect-krb5-sname.c detect-krb5-sname.h \
detect-l3proto.c detect-l3proto.h \
detect-lua.c detect-lua.h \
detect-lua-extensions.c detect-lua-extensions.h \

@ -178,7 +178,9 @@
#include "detect-geoip.h"
#include "detect-app-layer-protocol.h"
#include "detect-template.h"
#include "detect-krb5-cname.h"
#include "detect-krb5-msgtype.h"
#include "detect-krb5-sname.h"
#include "detect-target.h"
#include "detect-template-buffer.h"
#include "detect-bypass.h"
@ -491,7 +493,9 @@ void SigTableSetup(void)
DetectBase64DecodeRegister();
DetectBase64DataRegister();
DetectTemplateRegister();
DetectKrb5CNameRegister();
DetectKrb5MsgTypeRegister();
DetectKrb5SNameRegister();
DetectTargetRegister();
DetectTemplateBufferRegister();
DetectBypassRegister();

@ -198,6 +198,8 @@ enum {
DETECT_BASE64_DATA,
DETECT_AL_KRB5_MSGTYPE,
DETECT_AL_KRB5_CNAME,
DETECT_AL_KRB5_SNAME,
DETECT_TEMPLATE,
DETECT_FTPDATA,

@ -0,0 +1,245 @@
/* Copyright (C) 2018 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
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#include "suricata-common.h"
#include "util-unittest.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "detect-engine-state.h"
#include "detect-engine-prefilter.h"
#include "detect-engine-content-inspection.h"
#include "detect-krb5-cname.h"
#ifdef HAVE_RUST
#include "rust.h"
#include "app-layer-krb5.h"
#include "rust-krb-detect-gen.h"
static int g_krb5_cname_buffer_id = 0;
struct Krb5PrincipalNameDataArgs {
int local_id; /**< used as index into thread inspect array */
void *txv;
};
static int DetectKrb5CNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
DetectBufferSetActiveList(s, g_krb5_cname_buffer_id);
if (DetectSignatureSetAppProto(s, ALPROTO_KRB5) != 0)
return -1;
return 0;
}
/** \brief get an InspectionBuffer. Make space if we have to. */
static InspectionBuffer *GetBuffer(InspectionBufferMultipleForList *fb, uint32_t id)
{
if (id >= fb->size) {
uint32_t old_size = fb->size;
uint32_t new_size = id + 1;
uint32_t grow_by = new_size - old_size;
SCLogDebug("size is %u, need %u, so growing by %u",
old_size, new_size, grow_by);
void *ptr = SCRealloc(fb->inspection_buffers, (id + 1) * sizeof(InspectionBuffer));
if (ptr == NULL)
return NULL;
InspectionBuffer *to_zero = (InspectionBuffer *)ptr + old_size;
SCLogDebug("fb->inspection_buffers %p ptr %p to_zero %p",
fb->inspection_buffers, ptr, to_zero);
memset((uint8_t *)to_zero, 0, (grow_by * sizeof(InspectionBuffer)));
fb->inspection_buffers = ptr;
fb->size = new_size;
}
InspectionBuffer *buffer = &fb->inspection_buffers[id];
SCLogDebug("using file_data buffer %p", buffer);
return buffer;
}
static InspectionBuffer *GetKrb5CNameData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms,
Flow *_f, const struct Krb5PrincipalNameDataArgs *cbdata,
int list_id, bool first)
{
SCEnter();
InspectionBufferMultipleForList *fb = &det_ctx->multi_inspect_buffers[list_id];
InspectionBuffer *buffer = GetBuffer(fb, cbdata->local_id);
if (buffer == NULL)
return NULL;
if (!first && buffer->inspect != NULL)
return buffer;
uint32_t b_len = 0;
uint8_t *b = NULL;
if (rs_krb5_tx_get_cname(cbdata->txv, (uint16_t)cbdata->local_id, &b, &b_len) != 1)
return NULL;
if (b == NULL || b_len == 0)
return NULL;
InspectionBufferSetup(buffer, b, b_len);
InspectionBufferApplyTransforms(buffer, transforms);
SCReturnPtr(buffer, "InspectionBuffer");
}
static int DetectEngineInspectKrb5CName(
DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine,
const Signature *s,
Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
int local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv, };
InspectionBuffer *buffer = GetKrb5CNameData(det_ctx,
transforms, f, &cbdata, engine->sm_list, false);
if (buffer == NULL || buffer->inspect == NULL)
break;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd,
f,
(uint8_t *)buffer->inspect,
buffer->inspect_len,
buffer->inspect_offset, DETECT_CI_FLAGS_SINGLE,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL);
if (match == 1) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
typedef struct PrefilterMpmKrb5Name {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmKrb5Name;
/** \brief Krb5CName Krb5CName Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxKrb5CName(DetectEngineThreadCtx *det_ctx,
const void *pectx,
Packet *p, Flow *f, void *txv,
const uint64_t idx, const uint8_t flags)
{
SCEnter();
const PrefilterMpmKrb5Name *ctx = (const PrefilterMpmKrb5Name *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
int local_id = 0;
while(1) {
// loop until we get a NULL
struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer = GetKrb5CNameData(det_ctx, ctx->transforms,
f, &cbdata, list_id, true);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
&det_ctx->mtcu, &det_ctx->pmq,
buffer->inspect, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmKrb5NameFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmKrb5CNameRegister(DetectEngineCtx *de_ctx,
SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectMpmAppLayerRegistery *mpm_reg, int list_id)
{
PrefilterMpmKrb5Name *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->v2.transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxKrb5CName,
mpm_reg->v2.alproto, mpm_reg->v2.tx_min_progress,
pectx, PrefilterMpmKrb5NameFree, mpm_reg->name);
}
void DetectKrb5CNameRegister(void)
{
sigmatch_table[DETECT_AL_KRB5_CNAME].name = "krb5_cname";
sigmatch_table[DETECT_AL_KRB5_CNAME].Setup = DetectKrb5CNameSetup;
sigmatch_table[DETECT_AL_KRB5_CNAME].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_KRB5_CNAME].desc = "sticky buffer to match on Kerberos 5 client name";
DetectAppLayerMpmRegister2("krb5_cname", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmKrb5CNameRegister, NULL,
ALPROTO_KRB5, 1);
DetectAppLayerInspectEngineRegister2("krb5_cname",
ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectKrb5CName, NULL);
DetectBufferTypeSetDescriptionByName("krb5_cname",
"Kerberos 5 ticket client name");
g_krb5_cname_buffer_id = DetectBufferTypeGetByName("krb5_cname");
}
#else /* NO RUST */
void DetectKrb5CNameRegister(void) {}
#endif

@ -0,0 +1,29 @@
/* Copyright (C) 2015-2017 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
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#ifndef __DETECT_KRB5_CNAME_H__
#define __DETECT_KRB5_CNAME_H__
void DetectKrb5CNameRegister(void);
#endif /* __DETECT_KRB5_CNAME_H__ */

@ -0,0 +1,245 @@
/* Copyright (C) 2018 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
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#include "suricata-common.h"
#include "util-unittest.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "detect-engine-state.h"
#include "detect-engine-prefilter.h"
#include "detect-engine-content-inspection.h"
#include "detect-krb5-sname.h"
#ifdef HAVE_RUST
#include "rust.h"
#include "app-layer-krb5.h"
#include "rust-krb-detect-gen.h"
static int g_krb5_sname_buffer_id = 0;
struct Krb5PrincipalNameDataArgs {
int local_id; /**< used as index into thread inspect array */
void *txv;
};
static int DetectKrb5SNameSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
DetectBufferSetActiveList(s, g_krb5_sname_buffer_id);
if (DetectSignatureSetAppProto(s, ALPROTO_KRB5) != 0)
return -1;
return 0;
}
/** \brief get an InspectionBuffer. Make space if we have to. */
static InspectionBuffer *GetBuffer(InspectionBufferMultipleForList *fb, uint32_t id)
{
if (id >= fb->size) {
uint32_t old_size = fb->size;
uint32_t new_size = id + 1;
uint32_t grow_by = new_size - old_size;
SCLogDebug("size is %u, need %u, so growing by %u",
old_size, new_size, grow_by);
void *ptr = SCRealloc(fb->inspection_buffers, (id + 1) * sizeof(InspectionBuffer));
if (ptr == NULL)
return NULL;
InspectionBuffer *to_zero = (InspectionBuffer *)ptr + old_size;
SCLogDebug("fb->inspection_buffers %p ptr %p to_zero %p",
fb->inspection_buffers, ptr, to_zero);
memset((uint8_t *)to_zero, 0, (grow_by * sizeof(InspectionBuffer)));
fb->inspection_buffers = ptr;
fb->size = new_size;
}
InspectionBuffer *buffer = &fb->inspection_buffers[id];
SCLogDebug("using file_data buffer %p", buffer);
return buffer;
}
static InspectionBuffer *GetKrb5SNameData(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms,
Flow *_f, const struct Krb5PrincipalNameDataArgs *cbdata,
int list_id, bool first)
{
SCEnter();
InspectionBufferMultipleForList *fb = &det_ctx->multi_inspect_buffers[list_id];
InspectionBuffer *buffer = GetBuffer(fb, cbdata->local_id);
if (buffer == NULL)
return NULL;
if (!first && buffer->inspect != NULL)
return buffer;
uint32_t b_len = 0;
uint8_t *b = NULL;
if (rs_krb5_tx_get_sname(cbdata->txv, (uint16_t)cbdata->local_id, &b, &b_len) != 1)
return NULL;
if (b == NULL || b_len == 0)
return NULL;
InspectionBufferSetup(buffer, b, b_len);
InspectionBufferApplyTransforms(buffer, transforms);
SCReturnPtr(buffer, "InspectionBuffer");
}
static int DetectEngineInspectKrb5SName(
DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
const DetectEngineAppInspectionEngine *engine,
const Signature *s,
Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
int local_id = 0;
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}
while (1) {
struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv, };
InspectionBuffer *buffer = GetKrb5SNameData(det_ctx,
transforms, f, &cbdata, engine->sm_list, false);
if (buffer == NULL || buffer->inspect == NULL)
break;
det_ctx->buffer_offset = 0;
det_ctx->discontinue_matching = 0;
det_ctx->inspection_recursion_counter = 0;
const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd,
f,
(uint8_t *)buffer->inspect,
buffer->inspect_len,
buffer->inspect_offset, DETECT_CI_FLAGS_SINGLE,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL);
if (match == 1) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}
local_id++;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
typedef struct PrefilterMpmKrb5Name {
int list_id;
const MpmCtx *mpm_ctx;
const DetectEngineTransforms *transforms;
} PrefilterMpmKrb5Name;
/** \brief Krb5SName Krb5SName Mpm prefilter callback
*
* \param det_ctx detection engine thread ctx
* \param p packet to inspect
* \param f flow to inspect
* \param txv tx to inspect
* \param pectx inspection context
*/
static void PrefilterTxKrb5SName(DetectEngineThreadCtx *det_ctx,
const void *pectx,
Packet *p, Flow *f, void *txv,
const uint64_t idx, const uint8_t flags)
{
SCEnter();
const PrefilterMpmKrb5Name *ctx = (const PrefilterMpmKrb5Name *)pectx;
const MpmCtx *mpm_ctx = ctx->mpm_ctx;
const int list_id = ctx->list_id;
int local_id = 0;
while(1) {
// loop until we get a NULL
struct Krb5PrincipalNameDataArgs cbdata = { local_id, txv };
InspectionBuffer *buffer = GetKrb5SNameData(det_ctx, ctx->transforms,
f, &cbdata, list_id, true);
if (buffer == NULL)
break;
if (buffer->inspect_len >= mpm_ctx->minlen) {
(void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
&det_ctx->mtcu, &det_ctx->pmq,
buffer->inspect, buffer->inspect_len);
}
local_id++;
}
}
static void PrefilterMpmKrb5NameFree(void *ptr)
{
SCFree(ptr);
}
static int PrefilterMpmKrb5SNameRegister(DetectEngineCtx *de_ctx,
SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectMpmAppLayerRegistery *mpm_reg, int list_id)
{
PrefilterMpmKrb5Name *pectx = SCCalloc(1, sizeof(*pectx));
if (pectx == NULL)
return -1;
pectx->list_id = list_id;
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->v2.transforms;
return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxKrb5SName,
mpm_reg->v2.alproto, mpm_reg->v2.tx_min_progress,
pectx, PrefilterMpmKrb5NameFree, mpm_reg->name);
}
void DetectKrb5SNameRegister(void)
{
sigmatch_table[DETECT_AL_KRB5_SNAME].name = "krb5_sname";
sigmatch_table[DETECT_AL_KRB5_SNAME].Setup = DetectKrb5SNameSetup;
sigmatch_table[DETECT_AL_KRB5_SNAME].flags |= SIGMATCH_NOOPT;
sigmatch_table[DETECT_AL_KRB5_SNAME].desc = "sticky buffer to match on Kerberos 5 server name";
DetectAppLayerMpmRegister2("krb5_sname", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmKrb5SNameRegister, NULL,
ALPROTO_KRB5, 1);
DetectAppLayerInspectEngineRegister2("krb5_sname",
ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectKrb5SName, NULL);
DetectBufferTypeSetDescriptionByName("krb5_sname",
"Kerberos 5 ticket server name");
g_krb5_sname_buffer_id = DetectBufferTypeGetByName("krb5_sname");
}
#else /* NO RUST */
void DetectKrb5SNameRegister(void) {}
#endif

@ -0,0 +1,29 @@
/* Copyright (C) 2015-2017 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
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#ifndef __DETECT_KRB5_SNAME_H__
#define __DETECT_KRB5_SNAME_H__
void DetectKrb5SNameRegister(void);
#endif /* __DETECT_KRB5_SNAME_H__ */
Loading…
Cancel
Save