-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexercise_16
executable file
·61 lines (46 loc) · 1.7 KB
/
exercise_16
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
#!/usr/bin/env python3
# Copyright 2014 Carl Winbäck. See the COPYING file at the top-level directory
# of this distribution.
from os import urandom
import re
from libpals.util import (
aes_128_cbc_decrypt,
aes_128_cbc_encrypt,
numberlist_to_bytes,
pkcs7pad
)
SECRET_KEY = urandom(16)
IV = urandom(16)
def encrypt(user_input):
prefix = b'comment1=cooking%20MCs;userdata='
suffix = b';comment2=%20like%20a%20pound%20of%20bacon'
# Before encrypting we will remove any ampersands and equality signs, just
# like in challenge 13.
sanitized_user_input = re.sub(b'[&=]', b'', user_input)
plaintext = pkcs7pad(prefix + sanitized_user_input + suffix, 16)
ciphertext = aes_128_cbc_encrypt(SECRET_KEY, IV, plaintext)
return ciphertext
def is_admin(ciphertext):
plaintext = aes_128_cbc_decrypt(SECRET_KEY, IV, ciphertext)
result = re.search(b';admin=true;', plaintext)
return bool(result)
def attack(ciphertext):
ciphertext_list = list(ciphertext)
byte_x = ciphertext_list[37]
ciphertext_list[37] = byte_x ^ 1
byte_y = ciphertext_list[43]
ciphertext_list[43] = byte_y ^ 64
result = numberlist_to_bytes(ciphertext_list)
return result
# By crafting our input carefully we only need to flip two bits in the
# ciphertext in order to get the desired result.
plaintext_injection = b'LOOSE BITS SINK CHIPS:admin}true'
original_ciphertext = encrypt(plaintext_injection)
modified_ciphertext = attack(original_ciphertext)
result = is_admin(modified_ciphertext)
output_message = """SET 02 CHALLENGE 16: CBC bitflipping attacks
Input: {}
Is admin? {}
"""
print(output_message.format(plaintext_injection.decode('ascii'),
result))