Can you read the admin's email?
User: billy
Pass: TheKid
Solution
There's a mail system, if you input the given credentials..

..it will login and display a email sent from administrador.

...

I dug up the system and found no other functionality.
So, to read the email you do this POST request:
POST /viewmail/ HTTP/1.1
Host: lab.shellterlabs.com:32867
Content-Length: 63
Cache-Control: max-age=0
Origin: http://lab.shellterlabs.com:32867
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://lab.shellterlabs.com:32867/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: sessionid="billy:6405552caf11c7b1aa5b18a3346ae1f13eafa516"; csrftoken=s3iaLUoYZpWFkJaaMjvj8YOsCATokC9e
Connection: close
csrfmiddlewaretoken=s3iaLUoYZpWFkJaaMjvj8YOsCATokC9e&email_id=1
The csrfmiddlewaretoken has not working here, It just need to be equal the cookie csrftoken. But when you change the sessionid on cookie the request will fail:

Well, the challenge consists in read the email of the administrator. The footer gives the clue, the SHX Mail Administrator username is nealcaffrey.
To read the nealcaffrey email we need to forge his sessionid, but how?
I started by fuzzing the form fields and when I sent some symbols it triggered a django debuggin page displaying details from an exception and leaking part of the source code.


Nice, the administrator forgotten to disable Debug in a production environment, very common..
def generate_session_token(username):
user_hash = sha1(username).digest()
return stream_cipher(user_hash).encode('hex')
This code is showing us how the sessionid is created:
- The
user_hashis thehexofsha1("billy") sessionidis thehexresult of someStream Cipheralgorithm over theuser_hash
What is a Stream Cipher?
Wikipedia says: A stream cipher is a symmetric key cipher where plaintext digits are combined with a pseudorandom cipher digit stream (keystream). In a stream cipher, each plaintext digit is encrypted one at a time with the corresponding digit of the keystream, to give a digit of the ciphertext stream.
We don't know which algorithm is used, there's so much popular stream cipher algorithms out there, but the most common one is a simple XOR byte-per-byte and I bet the challenger used it. But to test it we need first recover the key used in encryption.
Recovering the key and the flag
- Create the
billy_user_hash - XOR byte-per-byte
billy_user_hashwithsessionid_hash - Now we can XOR the
keywith anyusername_user_hash, includingnealcaffrey_user_hashto get a validadmin sessionid
Final script
Just for note, you can replace this
xor_bytearray()function and part of this code by a simplehex(hex1 ^ hex2), because Python do axor byte-wiseby default in HEX values!

..and the flag

Thanks ShellterLabs and RoboCore, awesome contest!
intrd has spoken