Skip to content

Commit

Permalink
Merge pull request #40 from satta/dns-bloom-directions
Browse files Browse the repository at this point in the history
distinguish DNS query and answer in BLF alerting
  • Loading branch information
Robert Haist authored Mar 19, 2019
2 parents f82a9c5 + 97de123 commit 1aca672
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 10 deletions.
22 changes: 15 additions & 7 deletions processing/bloom_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -238,17 +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)) {
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 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)
Expand Down
73 changes: 70 additions & 3 deletions processing/bloom_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ import (

"github.com/DCSO/bloom"
log "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
)

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: ([^\" ]+)")
)

Expand All @@ -40,7 +42,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,
Expand All @@ -54,6 +57,7 @@ func makeBloomDNSEvent(rrname string) types.Entry {
Rrname: e.DNSRRName,
Rdata: e.DNSRData,
Rrtype: e.DNSRRType,
Type: e.DNSType,
},
}
json, err := json.Marshal(eve)
Expand Down Expand Up @@ -202,8 +206,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
}
Expand Down Expand Up @@ -738,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")
}
}

0 comments on commit 1aca672

Please # to comment.