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_hash
is thehex
ofsha1("billy")
sessionid
is thehex
result of someStream Cipher
algorithm 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_hash
withsessionid_hash
- Now we can XOR the
key
with anyusername_user_hash
, includingnealcaffrey_user_hash
to 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-wise
by default in HEX values!
..and the flag
Thanks ShellterLabs and RoboCore, awesome contest!