Secret Sheep Society

Category: Crypto
Points: 120
Description: The sheep are up to no good. They have a web portal for their secret society, which we have the source for. It seems fairly easy to join the organization, but climbing up its ranks is a different story.

I really liked this challenge. This was to do with bit flipping an AES_CBC encrypted text to change a false value to true.

We are presented with a webpage that you put in a name and it says hello $name you need to be admin to get flag essentially.

We have the source of the page and the important bit is when it session token which is of the form

    "admin": False,
    "handle": "name goes here"

This session is then AES_CBC encrypted and sent as cookie. Looking at the encryption steps in the script

def pack(self, session):
		cipher =, AES.MODE_CBC)
		iv = cipher.iv
		dec = json.dumps(session).encode()
		enc = cipher.encrypt(pad(dec, self.BLOCK_SIZE))
		raw = iv + enc
		return base64.b64encode(raw)

We see that the actually encrypted text is a padded version of this

{"admin": false, "handle": "a"}

Since this is using 16 block AES the cipher text that we recieve back in this case is IV + 16_BLOCK_CIPHER_TEXT + 16_BLOCK_CIPHER_TEXT now if you read how CBC works if you change a block it only effects the decryption of the following block. Now we only want to change the first block, because the first 16 bytes of the encrypted text is

# This is 16 bytes long
{"admin": false,

We want to start changing from ‘false,’ which is the last 6 bytes of the block. Now the first block is xor’d with the IV so we need to change the IV so that we can change the out put.

The formula to calculate this will be:
IV_BYTE ^ ORD(original_char) ^ ord(desired_char)

Which will give the byte of what to change it to. I wrote a simple python script to do this.

import binascii

def flip_bytes(iv_byte, orig, desired):
    return iv_byte ^ ord(orig) ^ ord(desired)

init_vector_byte = input("Init vector byte in hex: ")
init_vector_byte = int(init_vector_byte, 16)

original_value = input("Original value: ")
desired_value = input("Desired value: ")

new_value = flip_bytes(init_vector_byte, original_value, desired_value)
print("Value becomes %s" % hex(new_value))

So then flipping the bytes from 11 – 16 of the IV which will change “false,” to “true ,” (note the space)

This then will decrypt to be:

    "admin": true ,
    "handle" "a"

Base64 encoding the whole token again and then setting the token in the browser, reload the page and boom flag.