From 241db0cc66a046f273d78ecc4f4a341664a7351d Mon Sep 17 00:00:00 2001 From: evilsocket Date: Tue, 20 Feb 2018 11:33:30 +0100 Subject: [PATCH] fix: protecting concurrent access to LAN hosts --- modules/dhcp6_spoof.go | 8 +++---- modules/dns_spoof.go | 2 +- modules/net_recon.go | 7 +++--- modules/net_sniff_views.go | 3 +-- network/lan.go | 41 +++++++++++++++++++++++--------- session/session_core_handlers.go | 5 ++-- 6 files changed, 43 insertions(+), 23 deletions(-) diff --git a/modules/dhcp6_spoof.go b/modules/dhcp6_spoof.go index 489cd6ea..de18273e 100644 --- a/modules/dhcp6_spoof.go +++ b/modules/dhcp6_spoof.go @@ -154,8 +154,8 @@ func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet, } var ip net.IP - if t, found := s.Session.Lan.Hosts[target.String()]; found == true { - ip = t.IP + if h, found := s.Session.Lan.Get(target.String()); found == true { + ip = h.IP } else { log.Warning("Address %s not known, using random identity association address.", target.String()) rand.Read(ip) @@ -312,8 +312,8 @@ func (s *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.P addr = net.IP(raw[0]) } - if t, found := s.Session.Lan.Hosts[target.String()]; found == true { - log.Info("[%s] IPv6 address %s is now assigned to %s", core.Green("dhcp6"), addr.String(), t) + if h, found := s.Session.Lan.Get(target.String()); found == true { + log.Info("[%s] IPv6 address %s is now assigned to %s", core.Green("dhcp6"), addr.String(), h) } else { log.Info("[%s] IPv6 address %s is now assigned to %s", core.Green("dhcp6"), addr.String(), target) } diff --git a/modules/dns_spoof.go b/modules/dns_spoof.go index 54cfd43a..c10db635 100644 --- a/modules/dns_spoof.go +++ b/modules/dns_spoof.go @@ -111,7 +111,7 @@ func (s *DNSSpoofer) dnsReply(pkt gopacket.Packet, peth *layers.Ethernet, pudp * redir := fmt.Sprintf("(->%s)", s.Address) who := target.String() - if t, found := s.Session.Lan.Hosts[target.String()]; found == true { + if t, found := s.Session.Lan.Get(target.String()); found == true { who = t.String() } diff --git a/modules/net_recon.go b/modules/net_recon.go index 26e15bca..5a3b8241 100644 --- a/modules/net_recon.go +++ b/modules/net_recon.go @@ -71,11 +71,12 @@ func (d Discovery) Author() string { func (d *Discovery) runDiff(cache network.ArpTable) { // check for endpoints who disappeared var rem network.ArpTable = make(network.ArpTable) - for mac, t := range d.Session.Lan.Hosts { + + d.Session.Lan.EachHost(func(mac string, e *network.Endpoint) { if _, found := cache[mac]; found == false { - rem[mac] = t.IpAddress + rem[mac] = e.IpAddress } - } + }) for mac, ip := range rem { d.Session.Lan.Remove(ip, mac) diff --git a/modules/net_sniff_views.go b/modules/net_sniff_views.go index 7c471f9c..86244375 100644 --- a/modules/net_sniff_views.go +++ b/modules/net_sniff_views.go @@ -23,8 +23,7 @@ func vIP(ip net.IP) string { } address := ip.String() - host := session.I.Lan.Get(address) - + host := session.I.Lan.GetByIp(address) if host != nil { if host.Hostname != "" { return host.Hostname diff --git a/network/lan.go b/network/lan.go index da2532ed..37486f70 100644 --- a/network/lan.go +++ b/network/lan.go @@ -18,8 +18,8 @@ type LAN struct { Interface *Endpoint Gateway *Endpoint - Hosts map[string]*Endpoint + hosts map[string]*Endpoint ttl map[string]uint aliases *Aliases newCb EndpointNewCallback @@ -36,7 +36,7 @@ func NewLAN(iface, gateway *Endpoint, newcb EndpointNewCallback, lostcb Endpoint return &LAN{ Interface: iface, Gateway: gateway, - Hosts: make(map[string]*Endpoint), + hosts: make(map[string]*Endpoint), ttl: make(map[string]uint), aliases: aliases, newCb: newcb, @@ -49,7 +49,7 @@ func (lan *LAN) SetAliasFor(mac, alias string) bool { defer lan.Unlock() mac = NormalizeMac(mac) - if e, found := lan.Hosts[mac]; found { + if e, found := lan.hosts[mac]; found { lan.aliases.Set(mac, alias) e.Alias = alias return true @@ -57,12 +57,22 @@ func (lan *LAN) SetAliasFor(mac, alias string) bool { return false } +func (lan *LAN) Get(mac string) (*Endpoint, bool) { + lan.Lock() + defer lan.Unlock() + + if e, found := lan.hosts[mac]; found == true { + return e, true + } + return nil, false +} + func (lan *LAN) List() (list []*Endpoint) { lan.Lock() defer lan.Unlock() list = make([]*Endpoint, 0) - for _, t := range lan.Hosts { + for _, t := range lan.hosts { list = append(list, t) } return @@ -86,10 +96,10 @@ func (lan *LAN) Remove(ip, mac string) { lan.Lock() defer lan.Unlock() - if e, found := lan.Hosts[mac]; found { + if e, found := lan.hosts[mac]; found { lan.ttl[mac]-- if lan.ttl[mac] == 0 { - delete(lan.Hosts, mac) + delete(lan.hosts, mac) delete(lan.ttl, mac) lan.lostCb(e) } @@ -123,7 +133,7 @@ func (lan *LAN) Has(ip string) bool { lan.Lock() defer lan.Unlock() - for _, e := range lan.Hosts { + for _, e := range lan.hosts { if e.IpAddress == ip { return true } @@ -132,11 +142,20 @@ func (lan *LAN) Has(ip string) bool { return false } -func (lan *LAN) Get(ip string) *Endpoint { +func (lan *LAN) EachHost(cb func(mac string, e *Endpoint)) { lan.Lock() defer lan.Unlock() - for _, e := range lan.Hosts { + for m, h := range lan.hosts { + cb(m, h) + } +} + +func (lan *LAN) GetByIp(ip string) *Endpoint { + lan.Lock() + defer lan.Unlock() + + for _, e := range lan.hosts { if e.IpAddress == ip { return e } @@ -153,7 +172,7 @@ func (lan *LAN) AddIfNew(ip, mac string) *Endpoint { if lan.shouldIgnore(ip, mac) { return nil - } else if t, found := lan.Hosts[mac]; found { + } else if t, found := lan.hosts[mac]; found { if lan.ttl[mac] < LANDefaultttl { lan.ttl[mac]++ } @@ -162,7 +181,7 @@ func (lan *LAN) AddIfNew(ip, mac string) *Endpoint { e := NewEndpointWithAlias(ip, mac, lan.aliases.Get(mac)) - lan.Hosts[mac] = e + lan.hosts[mac] = e lan.ttl[mac] = LANDefaultttl lan.newCb(e) diff --git a/session/session_core_handlers.go b/session/session_core_handlers.go index 4670f13a..02f1ee2c 100644 --- a/session/session_core_handlers.go +++ b/session/session_core_handlers.go @@ -8,6 +8,7 @@ import ( "time" "github.com/evilsocket/bettercap-ng/core" + "github.com/evilsocket/bettercap-ng/network" "github.com/evilsocket/readline" ) @@ -298,11 +299,11 @@ func (s *Session) registerCoreHandlers() { readline.PcItem("alias", readline.PcItemDynamic(func(prefix string) []string { prefix = core.Trim(prefix[5:]) macs := []string{""} - for mac := range s.Lan.Hosts { + s.Lan.EachHost(func(mac string, e *network.Endpoint) { if prefix == "" || strings.HasPrefix(mac, prefix) == true { macs = append(macs, mac) } - } + }) return macs })))