llmnr: implement sticky buffers

Add detection keywords for LLMNR protocol inspection:
- llmnr.queries.rrname
- llmnr.answers.rrname
- llmnr.authorities.rrname
- llmnr.additionals.rrname
- llmnr.response.rrname

LLMNR reuses the existing DNS functions since it follows the same
protocol structure. The implementation registers LLMNR-specific keywords
that leverage the DNS data extraction functions.

Both to_server and to_client directions are supported.

Ticket #8366
pull/15509/head
Giuseppe Longo 2 months ago committed by Victor Julien
parent 8f205bb34f
commit 0b20011a9f

@ -51,6 +51,11 @@ static int mdns_answer_buffer_id = 0;
static int mdns_authority_buffer_id = 0;
static int mdns_additional_buffer_id = 0;
static int llmnr_query_buffer_id = 0;
static int llmnr_answer_buffer_id = 0;
static int llmnr_authority_buffer_id = 0;
static int llmnr_additional_buffer_id = 0;
static int DetectSetupDNS(DetectEngineCtx *de_ctx, Signature *s, const char *str, int id)
{
if (SCDetectBufferSetActiveList(de_ctx, s, id) < 0) {
@ -75,6 +80,18 @@ static int DetectSetupMDNS(DetectEngineCtx *de_ctx, Signature *s, const char *st
return 0;
}
static int DetectSetupLLMNR(DetectEngineCtx *de_ctx, Signature *s, const char *str, int id)
{
if (SCDetectBufferSetActiveList(de_ctx, s, id) < 0) {
return -1;
}
if (SCDetectSignatureSetAppProto(s, ALPROTO_LLMNR) < 0) {
return -1;
}
return 0;
}
static int SetupQueryBuffer(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{
return DetectSetupDNS(de_ctx, s, str, query_buffer_id);
@ -115,6 +132,26 @@ static int SetupAuthoritiesBufferMdns(DetectEngineCtx *de_ctx, Signature *s, con
return DetectSetupMDNS(de_ctx, s, str, mdns_authority_buffer_id);
}
static int SetupQueryBufferLlmnr(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{
return DetectSetupLLMNR(de_ctx, s, str, llmnr_query_buffer_id);
}
static int SetupAnswerBufferLlmnr(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{
return DetectSetupLLMNR(de_ctx, s, str, llmnr_answer_buffer_id);
}
static int SetupAdditionalsBufferLlmnr(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{
return DetectSetupLLMNR(de_ctx, s, str, llmnr_additional_buffer_id);
}
static int SetupAuthoritiesBufferLlmnr(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{
return DetectSetupLLMNR(de_ctx, s, str, llmnr_authority_buffer_id);
}
static int Register(const char *keyword, const char *desc, const char *doc,
int (*Setup)(DetectEngineCtx *, Signature *, const char *),
InspectionMultiBufferGetDataPtr GetBufferFn, AppProto alproto)
@ -166,4 +203,19 @@ void DetectDnsNameRegister(void)
Register("mdns.authorities.rrname", "mDNS authorities rrname sticky buffer",
"/rules/mdns-keywords.html#mdns-authorities-rrname", SetupAuthoritiesBufferMdns,
SCDnsTxGetAuthorityName, ALPROTO_MDNS);
llmnr_query_buffer_id = Register("llmnr.queries.rrname", "LLMNR query rrname sticky buffer",
"/rules/llmnr-keywords.html#llmnr-queries-rrname", SetupQueryBufferLlmnr,
SCDnsTxGetQueryName, ALPROTO_LLMNR);
llmnr_answer_buffer_id = Register("llmnr.answers.rrname", "LLMNR answer rrname sticky buffer",
"/rules/llmnr-keywords.html#llmnr-answers-rrname", SetupAnswerBufferLlmnr,
SCDnsTxGetAnswerName, ALPROTO_LLMNR);
llmnr_additional_buffer_id =
Register("llmnr.additionals.rrname", "LLMNR additionals rrname sticky buffer",
"/rules/llmnr-keywords.html#llmnr-additionals-rrname",
SetupAdditionalsBufferLlmnr, SCDnsTxGetAdditionalName, ALPROTO_LLMNR);
llmnr_authority_buffer_id =
Register("llmnr.authorities.rrname", "LLMNR authorities rrname sticky buffer",
"/rules/llmnr-keywords.html#llmnr-authorities-rrname",
SetupAuthoritiesBufferLlmnr, SCDnsTxGetAuthorityName, ALPROTO_LLMNR);
}

@ -35,6 +35,7 @@
static int detect_buffer_id = 0;
static int mdns_detect_buffer_id = 0;
static int llmnr_detect_buffer_id = 0;
typedef struct PrefilterMpm {
int list_id;
@ -82,6 +83,18 @@ static int MdnsDetectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *st
return 0;
}
static int LlmnrDetectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
{
if (SCDetectBufferSetActiveList(de_ctx, s, llmnr_detect_buffer_id) < 0) {
return -1;
}
if (SCDetectSignatureSetAppProto(s, ALPROTO_LLMNR) < 0) {
return -1;
}
return 0;
}
static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx, uint8_t flags,
const DetectEngineTransforms *transforms, void *txv, struct DnsResponseGetDataArgs *cbdata,
int list_id, bool get_rdata)
@ -349,6 +362,28 @@ static void SCDetectMdnsResponseRrnameRegister(void)
mdns_detect_buffer_id = DetectBufferTypeGetByName(keyword);
}
static void SCDetectLlmnrResponseRrnameRegister(void)
{
static const char *keyword = "llmnr.response.rrname";
int keyword_id = SCDetectHelperNewKeywordId();
sigmatch_table[keyword_id].name = keyword;
sigmatch_table[keyword_id].desc = "LLMNR response rrname buffer";
sigmatch_table[keyword_id].url = "/rules/llmnr-keywords.html#llmnr-response-rrname";
sigmatch_table[keyword_id].Setup = LlmnrDetectSetup;
sigmatch_table[keyword_id].flags |= SIGMATCH_NOOPT;
sigmatch_table[keyword_id].flags |= SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerInspectEngineRegister(
keyword, ALPROTO_LLMNR, SIG_FLAG_TOCLIENT, 1, DetectEngineInspectCb, NULL);
DetectAppLayerMpmRegister(keyword, SIG_FLAG_TOCLIENT, 2, DetectDnsResponsePrefilterMpmRegister,
NULL, ALPROTO_LLMNR, 1);
DetectBufferTypeSetDescriptionByName(keyword, "llmnr response rdata");
DetectBufferTypeSupportsMultiInstance(keyword);
llmnr_detect_buffer_id = DetectBufferTypeGetByName(keyword);
}
void DetectDnsResponseRegister(void)
{
static const char *keyword = "dns.response.rrname";
@ -371,4 +406,5 @@ void DetectDnsResponseRegister(void)
detect_buffer_id = DetectBufferTypeGetByName(keyword);
SCDetectMdnsResponseRrnameRegister();
SCDetectLlmnrResponseRrnameRegister();
}

Loading…
Cancel
Save