-
Notifications
You must be signed in to change notification settings - Fork 0
/
prob13.py
120 lines (105 loc) · 4.24 KB
/
prob13.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env python
# Written against python 3.3.1
# Matasano Problem 13
from prob11 import generateAESKey
from prob10 import aes_ecb_enc
from prob7 import aes_ecb_dec
from prob9 import addPKCS7Padding
# 13. ECB cut-and-paste
# Write a k=v parsing routine, as if for a structured cookie. The
# routine should take
# foo=bar&baz=qux&zap=zazzle
# and produce:
#
# {
# foo: 'bar',
# baz: 'qux',
# zap: 'zazzle'
# }
def parseKeyValue(cookie):
pairs = cookie.split("&");
arrayResult = [p.split("=",1) for p in pairs];
dictResult = {};
for x in arrayResult:
dictResult[x[0]] = x[1];
return dictResult;
# Now write a function that encodes a user profile in that format, given
# an email address. You should have something like:
# profile_for("[email protected]")
# and it should produce:
# {
# email: '[email protected]',
# uid: 10,
# role: 'user'
# }
# encoded as:
# [email protected]&uid=10&role=user
# Your "profile_for" function should NOT allow encoding metacharacters
# (& and =). Eat them, quote them, whatever you want to do, but don't
# let people set their email address to "[email protected]&role=admin".
def profile_for(email):
#remove =
email = ''.join(email.split("="));
#remove &
email = ''.join(email.split("&"));
result = "email=" + email + "&uid=10&role=user";
return result;
# Now, two more easy functions. Generate a random AES key, then:
# (a) Encrypt the encoded user profile under the key; "provide" that
# to the "attacker".
aesKey = generateAESKey();
def encryptProfile(profile):
return aes_ecb_enc(addPKCS7Padding(bytes(profile, 'UTF-8'), 16), aesKey);
def removePKCS7Padding(raw):
num = raw[len(raw)-1];
# should check padding values,
# but need to carefully consider what to do on an error...
return raw[0:(len(raw)-num)];
# (b) Decrypt the encoded user profile and parse it.
def decryptAndParseProfile(encProfile):
decProfile = aes_ecb_dec(encProfile, aesKey);
decProfile = removePKCS7Padding(decProfile);
profile = parseKeyValue(decProfile.decode('UTF-8'));
return profile;
# Using only the user input to profile_for() (as an oracle to generate
# "valid" ciphertexts) and the ciphertexts themselves, make a role=admin
# profile.
def makeAdminProfile():
# Observe:
# input "[email protected]" encrpts the blocks
# email=AAAA@BBBB. com&uid=10&role= user\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c
# input "XXXXXXXXXXadmin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\[email protected]" encrypts as:
# email=XXXXXXXXXX admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b @foo.com&uid...
# Want cipher matching:
# email=AAAA@BBBB. com&uid=10&role= admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b
input1 = "[email protected]";
input2 = "XXXXXXXXXXadmin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\[email protected]";
cipher1 = encryptProfile(profile_for(input1));
cipher2 = encryptProfile(profile_for(input2));
adminCipher = cipher1[0:32] + cipher2[16:32];
print("Admin Cipher: " + str(adminCipher));
print("Decrypted profile: " + str(decryptAndParseProfile(adminCipher)));
pass;
if __name__ == "__main__":
#test parseKeyValue;
testCookie = "foo=bar&baz=qux&zap=zazzle"
expectedParsedCookie= {"foo":"bar","baz":"qux","zap":"zazzle"};
actualParsedCookie = parseKeyValue(testCookie);
if (expectedParsedCookie != actualParsedCookie):
print("Failed parseCookie test");
print("Actual: " + str(actualParsedCookie));
print("Expected: " + str(expectedParsedCookie));
#test profile_for
email = "fo=o@b&ar.&com"
expectedProfile = "[email protected]&uid=10&role=user";
actualProfile = profile_for(email);
if (expectedProfile != actualProfile):
print("Failed profile_for test");
print("Actual: " + str(actualProfile));
print("Expected: " + str(expectedProfile));
decryptedCookie = decryptAndParseProfile(encryptProfile(testCookie));
if (decryptedCookie != actualParsedCookie):
print("Failed decrypt/encrypt test");
print("Actual: " + str(decryptedCookie));
print("Expected: " + str(actualParsedCookie));
makeAdminProfile();