Flip
Hey, do a flip! - by hadrian3689
Last updated
Hey, do a flip! - by hadrian3689
Last updated
The provided source code sets up a TCP
server that listens on the port 1337
. The client has to provide the encryption of the admin credentials to retrieve the flag. For this, the AES-CBC is used with a block size of 16 bytes.
On an incoming connection, the function start
is called, which generates a random key and IV and initiates the authentication process.
It prompts the client to provide a username and password and requests an admin login. The credentials of the admin are in cleartext visible in the source code. If a client attempts to log in as the admin with its credentials, the server sends a rejection; otherwise, the setup function is called. The setup function handles the authentication process for the flag.
In the setup function, a message is constructed with the provided username and password as follows:
access_username=USERNAME&password=PASSWORD
This message will be encrypted with AES-CBC, using the key and IV generated by the function start
. The message will then be leaked to the connected client. Next, the application asks for an encrypted message. This message will then be decrypted with the previously generated IV and key. If the decrypted string contains the information admin&password=sUp3rPaSs1
the flag will be provided.
Key and IV are not being leaked, so it is not possible to encrypt those credentials on our own. Using the admin credentials won't get us to the setup
function. To craft an encrypted text containing the admin credentials, the leaked encrypted message can be reused, referring to the AES-CBC bit flip attack. If we can control where the flip happens, we can create an encrypted message by providing the credentials, that are minimally changed by only one character, to pass the login prompt. Next, this changed character has to be flipped via the leaked cipher, so that it results in the correct credentials while decrypting the modified cipher text, to give us the flag.
For a more detailed view, this is how the AES-CBC encryption and decryption works.
In CBC mode, the plaintext is divided into blocks, and each block is XORed with the previous ciphertext block before being encrypted. This chaining process adds randomness and makes the encryption more secure. The first block is XORed with the so-called initialization vector. However, if an attacker can modify the ciphertext, they can change the corresponding plaintext block when decrypted.
Looking at the decryption process, its vice versa.
Changing a bit in the ciphertext leads to a complete wrongful decryption and affects every bit in the corresponding plaintext block, as visualized in red in the following graphic. But it also affects the single-bit XORed of the following plaintext block, visualized in green.
So, if we choose to put the string admin&password=sUp3rPaSs1\r\n
as the parameter for the username and \r\n
as the password, the complete plaintext will look like the following:
access_username=admin&password=sUp3rPaSs1\r\n&password=\r\n
In this case, the AES-CBC here encrypts in 16-byte blocks; if the block does not reach a length of 16 bytes, it is padded in the style of pkcs7. This results in the following plaintext blocks being encrypted.
Block 1: access_username=
Block 2: admin&password=s
Block 3: Up3rPaSs1\r\n&pass
Block 4: word=\r\n\t\t\t\t\t\t\t\t\t
We see that the first block just contains the string access_username=
which is not relevant to our authentication process. So we are able to choose to flip a bit in the first ciphertext block to change a character in the following plaintext block to result in the correct login credentials string, for the price of destroying the first plaintext block.
To create an input, that is being accepted by the function start
and its corresponding ciphertext is manipulable to create valid credentials with the AES-CBC bitflip attack, we choose to put the string bdmin&password=sUp3rPaSs1\r\n
as the parameter for the username and \r\n
as the password, the complete plaintext will look like the following:
access_username=bdmin&password=sUp3rPaSs1\r\n&password=\r\n
This allows us to flip the first byte from the letter b
to a
. The first byte of the first ciphertext has to be set to evaluate C_0_0 xor 'b' = 'a'
. To get the value for C_0_0
the formula just has to be changed to C_0_0 = 'a' xor 'b'
.
To test the bitflip offline, the following Python script encrypts the plaintextaccess_username=bdmin&password=sUp3rPaSs1\r\n&password=\r\n
and flips the first byte of the cipher to change the b
of bdmin
to a
.
As seen in the console output, the modified cipher leads to a string containing the necessary credentials, with the first part of the plaintext being destroyed.
To get the flag, we connect to the application via Pwn, pass the credentials as described, and retrieve the leaked encryption. Next, the cipher is being manipulated at the first byte, to change the second plaintext block to the desired result.
Run the script to get the flag.