From bb1f11e85ba068968e9fd81703b3ef5206192fa5 Mon Sep 17 00:00:00 2001 From: Sascha Steinbiss Date: Tue, 19 Mar 2019 15:38:29 +0100 Subject: [PATCH 1/2] distinguish DNS query and answer in BLF alerting --- processing/bloom_handler.go | 12 +++++++++--- processing/bloom_handler_test.go | 30 +++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/processing/bloom_handler.go b/processing/bloom_handler.go index c03ad2b..e0f0886 100644 --- a/processing/bloom_handler.go +++ b/processing/bloom_handler.go @@ -22,7 +22,8 @@ var sigs = map[string]string{ "http-url": "%s Possibly bad HTTP URL: ", "http-host": "%s Possibly bad HTTP host: ", "tls-sni": "%s Possibly bad TLS SNI: ", - "dns": "%s Possibly bad DNS lookup to ", + "dns-req": "%s Possibly bad DNS lookup to ", + "dns-resp": "%s Possibly bad DNS response for ", } // MakeAlertEntryForHit returns an alert Entry as raised by an external @@ -41,7 +42,7 @@ func MakeAlertEntryForHit(e types.Entry, eType string, alertPrefix string, ioc s value = fmt.Sprintf("%s | %s | %s", e.HTTPMethod, e.HTTPHost, e.HTTPUrl) } else if eType == "http-host" { value = e.HTTPHost - } else if eType == "dns" { + } else if strings.HasPrefix(eType, "dns") { value = e.DNSRRName } else if eType == "tls-sni" { value = e.TLSSni @@ -242,7 +243,12 @@ func (a *BloomHandler) Consume(e *types.Entry) error { if e.EventType == "dns" { a.Lock() if a.IocBloom.Check([]byte(e.DNSRRName)) { - n := MakeAlertEntryForHit(*e, "dns", a.AlertPrefix, e.DNSRRName) + var n types.Entry + if e.DNSType == "query" { + n = MakeAlertEntryForHit(*e, "dns-req", a.AlertPrefix, e.DNSRRName) + } else { + n = MakeAlertEntryForHit(*e, "dns-resp", a.AlertPrefix, e.DNSRRName) + } a.DatabaseEventChan <- n a.ForwardHandler.Consume(&n) } diff --git a/processing/bloom_handler_test.go b/processing/bloom_handler_test.go index 0e8257b..9543c3e 100644 --- a/processing/bloom_handler_test.go +++ b/processing/bloom_handler_test.go @@ -24,7 +24,8 @@ import ( var ( reHTTPURL = regexp.MustCompile(`Possibly bad HTTP URL: [^ ]+ . ([^ ]+) . ([^" ]+)`) reHTTPHost = regexp.MustCompile(`Possibly bad HTTP host: ([^" ]+)`) - reDNS = regexp.MustCompile("Possibly bad DNS lookup to ([^\" ]+)") + reDNSReq = regexp.MustCompile("Possibly bad DNS lookup to ([^\" ]+)") + reDNSRep = regexp.MustCompile("Possibly bad DNS response for ([^\" ]+)") reSNI = regexp.MustCompile("Possibly bad TLS SNI: ([^\" ]+)") ) @@ -40,7 +41,8 @@ func makeBloomDNSEvent(rrname string) types.Entry { DNSRCode: []string{"NOERROR", "NXDOMAIN"}[rand.Intn(2)], DNSRData: fmt.Sprintf("10.%d.0.%d", rand.Intn(50), rand.Intn(50)+100), DNSRRName: rrname, - DNSRRType: "answer", + DNSRRType: "A", + DNSType: []string{"answer", "query"}[rand.Intn(2)], } eve := types.EveEvent{ EventType: e.EventType, @@ -54,6 +56,7 @@ func makeBloomDNSEvent(rrname string) types.Entry { Rrname: e.DNSRRName, Rdata: e.DNSRData, Rrtype: e.DNSRRType, + Type: e.DNSType, }, } json, err := json.Marshal(eve) @@ -202,8 +205,29 @@ func (h *CollectorHandler) Consume(e *types.Entry) error { h.Entries[host] = true return nil } - match = reDNS.FindStringSubmatch(e.JSONLine) + match = reDNSReq.FindStringSubmatch(e.JSONLine) if match != nil { + var eve types.EveEvent + var err = json.Unmarshal([]byte(e.JSONLine), &eve) + if err != nil { + log.Fatal(err) + } + if eve.DNS.Type != "query" { + log.Fatalf("request alert for type (%s) != query", eve.DNS.Type) + } + h.Entries[match[1]] = true + return nil + } + match = reDNSRep.FindStringSubmatch(e.JSONLine) + if match != nil { + var eve types.EveEvent + var err = json.Unmarshal([]byte(e.JSONLine), &eve) + if err != nil { + log.Fatal(err) + } + if eve.DNS.Type != "answer" { + log.Fatalf("request alert for type (%s) != answer", eve.DNS.Type) + } h.Entries[match[1]] = true return nil } From 97de123995de781822a41ea106116ae72bfc6a74 Mon Sep 17 00:00:00 2001 From: Sascha Steinbiss Date: Tue, 19 Mar 2019 16:41:18 +0100 Subject: [PATCH 2/2] recognize invalid DNS types in EVE input --- processing/bloom_handler.go | 12 +++++---- processing/bloom_handler_test.go | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/processing/bloom_handler.go b/processing/bloom_handler.go index e0f0886..b12d4f8 100644 --- a/processing/bloom_handler.go +++ b/processing/bloom_handler.go @@ -239,22 +239,24 @@ func (a *BloomHandler) Consume(e *types.Entry) error { } a.Unlock() - } - if e.EventType == "dns" { + } else if e.EventType == "dns" { a.Lock() if a.IocBloom.Check([]byte(e.DNSRRName)) { var n types.Entry if e.DNSType == "query" { n = MakeAlertEntryForHit(*e, "dns-req", a.AlertPrefix, e.DNSRRName) - } else { + } else if e.DNSType == "answer" { n = MakeAlertEntryForHit(*e, "dns-resp", a.AlertPrefix, e.DNSRRName) + } else { + log.Warnf("invalid DNS type: '%s'", e.DNSType) + a.Unlock() + return nil } a.DatabaseEventChan <- n a.ForwardHandler.Consume(&n) } a.Unlock() - } - if e.EventType == "tls" { + } else if e.EventType == "tls" { a.Lock() if a.IocBloom.Check([]byte(e.TLSSni)) { n := MakeAlertEntryForHit(*e, "tls-sni", a.AlertPrefix, e.TLSSni) diff --git a/processing/bloom_handler_test.go b/processing/bloom_handler_test.go index 9543c3e..491a889 100644 --- a/processing/bloom_handler_test.go +++ b/processing/bloom_handler_test.go @@ -19,6 +19,7 @@ import ( "github.com/DCSO/bloom" log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus/hooks/test" ) var ( @@ -762,5 +763,47 @@ func TestBloomHandlerURL(t *testing.T) { if len(fwhandler.GetEntries()) != 0 { t.Fatalf("too many alerts: %d", len(fwhandler.GetEntries())) } +} +func TestBloomHandlerInvalidDNS(t *testing.T) { + // make sure that alerts are forwarded + util.PrepareEventFilter([]string{"alert"}, false) + + // initalize Bloom filter and fill with 'interesting' values + bf := bloom.Initialize(100000, 0.0000001) + + // channel to receive events to be saved to database + dbChan := make(chan types.Entry) + + // handler to receive forwarded events + fwhandler := &CollectorHandler{ + Entries: make(map[string]bool), + } + + // concurrently gather entries to be written to DB + dbWritten := make([]types.Entry, 0) + consumeWaitChan := make(chan bool) + go func() { + for e := range dbChan { + dbWritten = append(dbWritten, e) + } + close(consumeWaitChan) + }() + + bh := MakeBloomHandler(&bf, dbChan, fwhandler, "FOO BAR") + e := makeBloomDNSEvent("foobar") + e.DNSType = "foobar" + bf.Add([]byte(e.DNSRRName)) + + hook := test.NewGlobal() + + bh.Consume(&e) + + entries := hook.AllEntries() + if len(entries) < 1 { + t.Fatal("missing log entries") + } + if entries[0].Message != "invalid DNS type: 'foobar'" { + t.Fatal("wrong log entry for invalid DNS type") + } }