-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathc31_server.py
78 lines (64 loc) · 2.72 KB
/
c31_server.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 hmac, time
from flask import Flask, request
app = Flask(__name__)
@app.route("/verify")
def verify():
#get query params
file = request.args.get("file")
signature = request.args.get("signature")
#make sure we have the params
if not file or not signature:
return "missing query parameters; send in both file and signature\n"
#verify signature byte at a time
if insecure_compare(file.encode(), signature):
return "valid\n", 200
#no match
return "invalid\n", 500
#byte at a time verification with artificial delays
def insecure_compare(file, test_sig):
#hash user input
good_sig = get_hmac(file)
#test against signature byte at a time
for i in range(len(good_sig)):
if i >= len(test_sig):
return False
if good_sig[i] != test_sig[i]:
return False
#add artificial delay
time.sleep(.005)
#hashes match
return True
def get_hmac(file):
h = hmac.new(b'foo')
h.update(file)
return h.hexdigest()
if __name__ == "__main__":
app.run()
'''
Implement and break HMAC-SHA1 with an artificial timing leak
The psuedocode on Wikipedia should be enough. HMAC is very easy.
Using the web framework of your choosing (Sinatra, web.py, whatever),
write a tiny application that has a URL that takes a "file" argument
and a "signature" argument, like so:
http://localhost:9000/test?file=foo&signature=46b4ec586117154dacd49d664e5d63fdc88efb51
Have the server generate an HMAC key, and then verify that the "signature"
on incoming requests is valid for "file", using the "==" operator to compare
the valid MAC for a file with the "signature" parameter (in other words,
verify the HMAC the way any normal programmer would verify it).
Write a function, call it "insecure_compare", that implements the
== operation by doing byte-at-a-time comparisons with early exit (ie,
return false at the first non-matching byte).
In the loop for "insecure_compare", add a 50ms sleep (sleep 50ms after each byte).
Use your "insecure_compare" function to verify the HMACs on incoming
requests, and test that the whole contraption works. Return a 500 if
the MAC is invalid, and a 200 if it's OK.
Using the timing leak in this application, write a program that
discovers the valid MAC for any file.
Why artificial delays?
Early-exit string compares are probably the most common source of
cryptographic timing leaks, but they aren't especially easy to exploit.
In fact, many timing leaks (for instance, any in C, C++, Ruby, or Python)
probably aren't exploitable over a wide-area network at all. To play with
attacking real-world timing leaks, you have to start writing low-level
timing code. We're keeping things cryptographic in these challenges.
'''