Wednesday 15 January 2014

[HACKYOU 2014] Crypto200 - HashMe

So in this challenge, you are given a python script and the address of a server where the script is being run. Upon inspecting the script you can see that it allows you to register and also to log in. When a user logs in as an administrator, the script will automatically spit out the password. However, in the script given to us, the KEY and SALT have both been removed.



When a user registers, he is given a certificate that he can use to log in to the system; this certificate consisting of the user's username, role, hash of the username and role, all xor'ed against the KEY and then base64 encoded. Since we have access to the certificate post-xor and we do know what part of the plaintext was ( the username and the role ), we can recover the KEY. We can manipulate the username to be as long as necessary in order to recover the entire key.



Using this method, I found the key to be 28c1150dac6704583d6c1125a72d3c87241e7f5497e9b80c78f4ce2b08dcab2b0df20be0abde0b17512a935bc765607cf5e5 when hex encoded.

Now that we have the key, we're free to obtain the auth string and the hash from any certificate issued by that particular script on that server. Looking closely at the code, it doesn't seem likely that obtaining the SALT is possible but we do see that the code searches for "administrator" in the data['role'] list. What this tells us is that it is possible for us to successfully pass the admin check even if we have more than one role present in our auth string.

It turns out that we can simply add "&role=administrator" to the end of the auth string and that works out fine. However, we still have to deal with the md5 hash of that auth string. Luckily for us, the hashing algorithm used in the script is vulnerable to a length extension attack. We can use the hash given to us in the certificate ( using the key we recovered earlier ), to discover the internal state ( A,B,C,D ) of the hashing function at the end of its operation. We can then use that state in place of the IV we usually start with and continue to hash our newly added role.

However, the hashing algorithm state, depends not only on A,B,C and D but also on the number of bytes processed up to that point (modulo 32). At this point, this value is purely dependent on the length of the SALT which is still unknown to us but we know that there are only 32 possible values for this aspect of the state and therefore it can be bruteforced.



Using the script above, I was able to generate the 32 candidate certificates for a particular user that comply with the SALT and KEY present in the script on the server. The 21st certificate was accepted, meaning that the length of the SALT was 20 bytes and then the flag was spit out.


[HACKYOU 2014] crypto300 - Matrix

So for this crypto challenge, you're given a file, encrypter.py, and another file, flag.wmv.out. Looking at the encrypter file, you can tell that the original file is broken up into blocks of 16 bytes each which are then transformed into 4x4 matrices. Each of these matrices is then multiplied by a key that was generated earlier and the resulting matrix is turned back into a string of bytes and written to the output file.



The key to this challenge was to take a look at the specification for the file format.
WMV file is in most circumstances encapsulated in the Advanced Systems Format (ASF) container format.
Looking at the ASF specification, these types of file usually start with a 16 byte GUID that identifies the file type. This hints at a known-plaintext attack. Using some basic linear algebra, given the plaintext and the ciphertext for the first 16 bytes of the file, it is possible to recover the key matrix. Once this key matrix is recovered, the rest of the file can be decrypted and the original wmv file can be recovered. The details of the steps involving the calculations are explained in comments in the code below.



Once the file has been decrypted, the wmv file is playable and it reveals the flag.