Skip to main content

Hackim18 - Web1

·3 mins·
Crypto Web Write-Up Ctf
Table of Contents
Hackim18 - This article is part of a series.
Part 3: This Article

Description
#

The objective of this challenge is to find a way to get logged in as the user “administrator”.

This is the demo application for our new session management system based on military cryptography (namely CBC-MAC). You can log in as any user (except ‘administrator’) with the password ‘Password1’. We blocked access to ‘administrator’ account for security reasons.

Resolution
#

Let’s log in with the username “test” and see how the authentication system keeps track of the currently logged in user.

There are 2 cookies encoded in base64. One just needs to decode them to see their real value and get a better understanding of what’s going on.

"dGVzdC0trPGLxEtxTi8=".decode("base64")
# 'test--\xac\xf1\x8b\xc4KqN/'
"bOHCrEKzfso=".decode("base64")
# 'l\xe1\xc2\xacB\xb3~\xca'

Excellent ! So the “auth” cookie is just the username followed by “–” and 8 bytes which corresponds to the output of the CBC-MAC algorithm. The “iv” cookie is, like its name says, the initialization vector used by the CBC-MAC algorithm to produce the above result.

A little bit of crypto
#

CBC-MAC (Cipher Block Chaining Message Authentication Code) uses blocks of fixed length to encrypt a message and output only the last block of the resulting ciphertext. This is the one present at the end of the “auth” cookie and its size is 8 bytes.

Unlike other block ciphers, CBC-MAC uses a fixed IV, usually zero. The IV and the plaintext are then xored together. Since the IV and the plaintext can be modified, one can forge a first block that will output the same authentication code ! More information about why it’s insecure to have a variable IV is described in this blog post.

Ok, it’s possible to change the first 8 bytes of the plaintext without repercussions on the authentication code but “administrator” is 13 bytes long. Logging in with a username which is 13 bytes long and ends with “rator” will solve the problem. The less change needed, the quicker, that’s why using “Administrator” is a good choice, only the first letter will have to be changed.

iv = "Gzb5ZaA8QUo=".decode("base64")
iv
# '\x1b6\xf9e\xa0<AJ'
auth = "QWRtaW5pc3RyYXRvci0tzyp2t0HMVVI=".decode("base64")
auth
# 'Administrator--\xcf*v\xb7A\xccUR'

Before changing the first letter, the current value of the first byte of the first block must be calculated.

ord('A')^0x1b
# 90

The first letter of the username needs to be replaced with ‘a’, therefore the first byte of the IV needs to be changed to produce the same result as before:

ord('a')^90
# 59
chr(59)
# ';'

Now, the new values just have to be encoded in base64 and changed in the browser.

'administrator--\xcf*v\xb7A\xccUR'.encode("base64")
# 'YWRtaW5pc3RyYXRvci0tzyp2t0HMVVI=\n'
';6\xf9e\xa0<AJ'.encode('base64')
# 'Ozb5ZaA8QUo=\n'

Validation can be done with the flag: hackim18{'cbc_it_is_easy_as_one_two_three'}

Hackim18 - This article is part of a series.
Part 3: This Article