def chall_four(unknown_string): unknown_hex = base64.b64decode(unknown_string).hex() found_block_sizes = find_cipher_block_size(unknown_hex) block_size = found_block_sizes[1] - found_block_sizes[0] my_string = ("A" * block_size * 3).encode().hex( ) # want to pad >2 block lengths to detect repetition (i.e. force message to have 2 equivalent blocks) padded_msg = pkcs7_pad(my_string + unknown_hex, block_size) (ciphertext, CipherObj) = aes_ecb_encrypt_with_key(bytes.fromhex(padded_msg), bytes.fromhex(key)) ciphertext = ciphertext.hex() ecb_detected = detect_ecb(ciphertext) if not ecb_detected: print("ECB not detected; not exploitable") return # now we know the block size, and it's in ECB decrypted_blocks = ''.join([ padding_oracle(unknown_hex[i:i + block_size * 2], block_size, '') for i in range(0, len(unknown_hex), block_size * 2) ]) #unpad string padding = ord(decrypted_blocks[-1]) decrypted_blocks = decrypted_blocks[:-padding] return decrypted_blocks
def cbc_encrypt(msg, key, iv): # check that msg == hex, key == hex, iv == hex # I should probably handle these better but whatever assert int(msg, 16) assert int(key, 16) assert int(iv, 16) padded_msg = pkcs7_pad(msg, block_size) msg_blocks = [ padded_msg[i:(i + block_size * 2)] for i in range(0, len(padded_msg), block_size * 2) ] iv_first_block = xor_hex_strings(iv, msg_blocks[0]) (block_0, encryptor) = aes_ecb_encrypt_with_key(bytes.fromhex(iv_first_block), bytes.fromhex(key)) block_i = block_0 ctext = [block_i.hex()] for msg_block in msg_blocks: iv_i = xor_hex_strings(block_i.hex(), msg_block) (block_i, encryptor) = aes_ecb_encrypt_with_key(bytes.fromhex(iv_i), bytes.fromhex(key)) ctext.append(block_i.hex()) return ''.join(ctext)
def encryption_oracle(msg): rand_count = random.randint(5, 10) prepad_msg = get_random_int( rand_count * 8) + msg.encode().hex() + get_random_int(rand_count * 8) padded_msg = pkcs7_pad(prepad_msg.encode().hex(), 16) #print(padded_msg) ciphertext = '' key = get_random_int(128) iv = get_random_int(128) if random.getrandbits(1): ciphertext = cbc_encrypt(padded_msg, key, iv) else: (ciphertext, CipherObj) = aes_ecb_encrypt_with_key(bytes.fromhex(padded_msg), bytes.fromhex(key)) ciphertext = ciphertext.hex() return ciphertext
def encryption_oracle(input_string): input_string = urllib.parse.quote(input_string) plaintext = '"comment1"="cooking%20MCs";"userdata"="' + input_string + '";"comment2"="%20like%20a%20pound%20of%20bacon"' plaintext = pkcs7_pad(plaintext.encode().hex(), block_size) return aes_ctr_operation(key, plaintext, nonce)
def generic_encrypt_ecb(msg, key, block_size): (ciphertext, CipherObj) = aes_ecb_encrypt_with_key( bytes.fromhex(pkcs7_pad(msg, block_size)), bytes.fromhex(key)) return ciphertext.hex()
def encrypt_profile(input_string): padded_string = pkcs7_pad(input_string.encode().hex(), 16) return aes_ecb_encrypt_with_key(bytes.fromhex(padded_string), bytes.fromhex(key))
formatted_cookie = f"email={input_string}&uid={rand_int}&role=user" add_cookie_to_json(formatted_cookie, my_dict) def encrypt_profile(input_string): padded_string = pkcs7_pad(input_string.encode().hex(), 16) return aes_ecb_encrypt_with_key(bytes.fromhex(padded_string), bytes.fromhex(key)) def decrypt_profile(ciphertext, CipherObj): return aes_ecb_decrypt(CipherObj, ciphertext) # json format: {"email": "<email>", "uid": "10", "role": "user"} # attacker knows: ciphertext, and format of plaintext (but in a real scenario, UID might be more randomized) my_dict = {} email = "*****@*****.**" + bytes.fromhex(pkcs7_pad('"admin"}'.encode().hex(), 16)).decode() profile_for(email, my_dict) (ciphertext, CipherObj) = encrypt_profile(json.dumps(my_dict)) # cut off first two bytes (email) to get admin ciphertext admin_ciphertext = ciphertext[32:48] # 2) pad "admin" ciphertext onto encrypted cookie such that ciphertext ends in "role=" my_dict = {} email = "*****@*****.**" profile_for(email, my_dict) (ciphertext, CipherObj) = encrypt_profile(json.dumps(my_dict)) # cut first 48 bytes and append with step 1 ciphertext; 48 = length of formatted json plaintext = decrypt_profile(ciphertext[:48] + admin_ciphertext, CipherObj)