mirror of
https://github.com/bettercap/bettercap
synced 2025-07-05 20:42:09 -07:00
new: gateway.change event for MITM monitoring
This commit is contained in:
parent
43a93fd866
commit
c47e3f6195
8 changed files with 144 additions and 5 deletions
|
@ -36,4 +36,7 @@ onEvent('wifi.client.handshake', onHandshake);
|
||||||
onEvent('wifi.ap.new', onNewAP);
|
onEvent('wifi.ap.new', onNewAP);
|
||||||
|
|
||||||
// register for new nodes in the graph
|
// register for new nodes in the graph
|
||||||
onEvent('graph.node.new', onNewNode);
|
onEvent('graph.node.new', onNewNode);
|
||||||
|
|
||||||
|
// register for gateway changes
|
||||||
|
onEvent('gateway.change', onGatewayChange)
|
|
@ -90,6 +90,17 @@ function onNewNode(event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onGatewayChange(event) {
|
||||||
|
var change = event.data;
|
||||||
|
|
||||||
|
var message = '🚨 Detected ' + change.type + ' gateway change, possible MITM attack:\n\n' +
|
||||||
|
'Prev: ' + change.prev.ip + ' (' + change.prev.mac + ")\n" +
|
||||||
|
'New: ' + change.new.ip + ' (' + change.new.mac + ")";
|
||||||
|
|
||||||
|
// send to telegram bot
|
||||||
|
sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
function onTick(event) {
|
function onTick(event) {
|
||||||
run('wifi.probe ' + fakeBSSID + ' ' + fakeESSID);
|
run('wifi.probe ' + fakeBSSID + ' ' + fakeESSID);
|
||||||
}
|
}
|
|
@ -129,6 +129,8 @@ func (mod *EventsStream) Render(output io.Writer, e session.Event) {
|
||||||
mod.viewUpdateEvent(output, e)
|
mod.viewUpdateEvent(output, e)
|
||||||
} else if strings.HasPrefix(e.Tag, "graph.") {
|
} else if strings.HasPrefix(e.Tag, "graph.") {
|
||||||
mod.viewGraphEvent(output, e)
|
mod.viewGraphEvent(output, e)
|
||||||
|
} else if e.Tag == "gateway.change" {
|
||||||
|
mod.viewGatewayEvent(output, e)
|
||||||
} else if e.Tag != "tick" {
|
} else if e.Tag != "tick" {
|
||||||
fmt.Fprintf(output, "[%s] [%s] %v\n", e.Time.Format(mod.timeFormat), tui.Green(e.Tag), e)
|
fmt.Fprintf(output, "[%s] [%s] %v\n", e.Time.Format(mod.timeFormat), tui.Green(e.Tag), e)
|
||||||
}
|
}
|
||||||
|
|
23
modules/events_stream/events_view_gateway.go
Normal file
23
modules/events_stream/events_view_gateway.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package events_stream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/tui"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (mod *EventsStream) viewGatewayEvent(output io.Writer, e session.Event) {
|
||||||
|
change := e.Data.(session.GatewayChange)
|
||||||
|
|
||||||
|
fmt.Fprintf(output, "[%s] [%s] %s gateway changed: '%s' (%s) -> '%s' (%s)\n",
|
||||||
|
e.Time.Format(mod.timeFormat),
|
||||||
|
tui.Red(e.Tag),
|
||||||
|
string(change.Type),
|
||||||
|
change.Prev.IP,
|
||||||
|
change.Prev.MAC,
|
||||||
|
change.New.IP,
|
||||||
|
change.New.MAC)
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package network
|
||||||
|
|
||||||
import "regexp"
|
import "regexp"
|
||||||
|
|
||||||
var ArpTableParser = regexp.MustCompile(`^([a-f\d\.:]+)\s+dev\s+(\w+)\s+\w+\s+([a-f0-9:]{17})\s+\w+$`)
|
var ArpTableParser = regexp.MustCompile(`^([a-f\d\.:]+)\s+dev\s+(\w+)\s+\w+\s+([a-f0-9:]{17})\s+.+$`)
|
||||||
var ArpTableTokens = 4
|
var ArpTableTokens = 4
|
||||||
var ArpTableTokenIndex = []int{1, 3, 2}
|
var ArpTableTokenIndex = []int{1, 3, 2}
|
||||||
var ArpCmd = "ip"
|
var ArpCmd = "ip"
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package routing
|
package routing
|
||||||
|
|
||||||
type RouteType int
|
type RouteType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
IPv4 RouteType = 0
|
IPv4 RouteType = "IPv4"
|
||||||
IPv6 RouteType = 1
|
IPv6 RouteType = "IPv6"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Route struct {
|
type Route struct {
|
||||||
|
|
|
@ -255,8 +255,12 @@ func (s *Session) Start() error {
|
||||||
s.Events.Log(level, "%s", err.Error())
|
s.Events.Log(level, "%s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we are the gateway
|
||||||
if s.Gateway == nil || s.Gateway.IpAddress == s.Interface.IpAddress {
|
if s.Gateway == nil || s.Gateway.IpAddress == s.Interface.IpAddress {
|
||||||
s.Gateway = s.Interface
|
s.Gateway = s.Interface
|
||||||
|
} else {
|
||||||
|
// start monitoring for gateway changes
|
||||||
|
go s.routeMon()
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Firewall = firewall.Make(s.Interface)
|
s.Firewall = firewall.Make(s.Interface)
|
||||||
|
|
96
session/session_routing.go
Normal file
96
session/session_routing.go
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/bettercap/bettercap/network"
|
||||||
|
"github.com/bettercap/bettercap/routing"
|
||||||
|
"github.com/evilsocket/islazy/log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type gateway struct {
|
||||||
|
IP string `json:"ip"`
|
||||||
|
MAC string `json:"mac"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GatewayChange struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Prev gateway `json:"prev"`
|
||||||
|
New gateway `json:"new"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) routeMon() {
|
||||||
|
var err error
|
||||||
|
var gw4 *network.Endpoint
|
||||||
|
var gwIP6, gwMAC6 string
|
||||||
|
|
||||||
|
s.Events.Log(log.INFO, "gateway monitor started ...")
|
||||||
|
|
||||||
|
gw4 = s.Gateway
|
||||||
|
|
||||||
|
gwIP6, err = routing.Gateway(routing.IPv6, s.Interface.Name())
|
||||||
|
if err != nil {
|
||||||
|
s.Events.Log(log.ERROR, "error getting ipv6 gateway: %v", err)
|
||||||
|
} else if gwIP6 != "" {
|
||||||
|
gwMAC6, err = network.ArpLookup(s.Interface.Name(), gwIP6, true)
|
||||||
|
if err != nil {
|
||||||
|
s.Events.Log(log.DEBUG, "error getting %s ipv6 gateway mac: %v", gwIP6, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
s.Events.Log(log.DEBUG, "[gw] ipv4=%s(%s) ipv6=%s(%s)", gw4.IP, gw4.HwAddress, gwIP6, gwMAC6)
|
||||||
|
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
gw4now, err := network.FindGateway(s.Interface)
|
||||||
|
if err != nil {
|
||||||
|
s.Events.Log(log.ERROR, "error getting ipv4 gateway: %v", err)
|
||||||
|
} else if gw4now == nil {
|
||||||
|
s.Events.Log(log.ERROR, "null ipv4 gateway")
|
||||||
|
} else {
|
||||||
|
if gw4now.IpAddress != gw4.IpAddress || gw4now.HwAddress != gw4.HwAddress {
|
||||||
|
s.Events.Add("gateway.change", GatewayChange{
|
||||||
|
Type: string(routing.IPv4),
|
||||||
|
Prev: gateway{
|
||||||
|
IP: gw4.IpAddress,
|
||||||
|
MAC: gw4.HwAddress,
|
||||||
|
},
|
||||||
|
New: gateway{
|
||||||
|
IP: gw4now.IpAddress,
|
||||||
|
MAC: gw4now.HwAddress,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gw4 = gw4now
|
||||||
|
|
||||||
|
gwMAC6now := ""
|
||||||
|
gwIP6now, err := routing.Gateway(routing.IPv6, s.Interface.Name())
|
||||||
|
if err != nil {
|
||||||
|
s.Events.Log(log.ERROR, "error getting ipv6 gateway: %v", err)
|
||||||
|
} else if gwIP6now != "" {
|
||||||
|
gwMAC6now, err = network.ArpLookup(s.Interface.Name(), gwIP6now, true)
|
||||||
|
if err != nil {
|
||||||
|
s.Events.Log(log.DEBUG, "error getting %s ipv6 gateway mac: %v", gwIP6now, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if gwIP6now != gwIP6 || gwMAC6now != gwMAC6 {
|
||||||
|
s.Events.Add("gateway.change", GatewayChange{
|
||||||
|
Type: string(routing.IPv6),
|
||||||
|
Prev: gateway{
|
||||||
|
IP: gwIP6,
|
||||||
|
MAC: gwMAC6,
|
||||||
|
},
|
||||||
|
New: gateway{
|
||||||
|
IP: gwIP6now,
|
||||||
|
MAC: gwMAC6now,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
gwIP6 = gwIP6now
|
||||||
|
gwMAC6 = gwMAC6now
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue