DEV Community

Cover image for Hack The Box Writeup: Emdee Five for Life
SSHad0w
SSHad0w

Posted on

Hack The Box Writeup: Emdee Five for Life

Hello hackers! Today we'll cover a quick and fun scripting challenge using python. This is the first challenge on the Intro to Dante track on Hack The Box which is described as:
"Practice machines and challenges to help you prepare for the Dante Pro Lab."

Introduction

For this challenge, we're met with a website that presents us with a prompt and field. The field says "MD5" in it, suggesting that we're expected to submit the MD5 hash version of the text.

Image description

Methodology:

I looked up an MD5 hash generator website to complete the challenge. I inputted the string, copied the hash, and I was met with an unfavorable response:

Image description

The site changed the text provided and told me I was "Too slow!". Since I didn't appreciate it's teasing, I decided to boost my speed with a bespoke solution to this challenge.

Identifying the template

First, I need to see what a normal raw response looks like from this server, so I'm able to parse out the relevant data, hash it, and submit a response programmatically. For that reason, I don't think burp suite will help me here, as it won't give me a view of how it needs to be parsed. I think python will get the job done well.

Grabbing the response

I opened up the greatest editor of all time and wrote:

import requests
response = requests.get('http://134.209.176.83:30536') # change this for your instance!
print(response.content)
Enter fullscreen mode Exit fullscreen mode

It's extremely simple, but it did the trick. Running this code gave me a response like the following:

b'<html>\n<head>\n<title>emdee five for life</title>\n</head>\n<body style="background-color:powderblue;">\n<h1 align=\'center\'>MD5 encrypt this string</h1><h3 align=\'center\'>c3WOTbjAmW4hFDHQpCjZ</h3><center><form action="" method="post">\n<input type="text" name="hash" placeholder="MD5" align=\'center\'></input>\n</br>\n<input type="submit" value="Submit"></input>\n</form></center>\n</body>\n</html>\n'
Enter fullscreen mode Exit fullscreen mode

I ran it a few more times to make sure I had a good understanding of the format.

Great! Now all I need to do is pluck out the relevant information in the response.

Parsing the output

I tried parsing the output using classic python methods like .split(), but I ran into the following.

TypeError: byte indices must be integers or slices, not str
Enter fullscreen mode Exit fullscreen mode

Turns out this was still raw bytes, instead of a proper string type.

The following update to my code fixed this issue:

import requests
response = requests.get('http://134.209.176.83:30536')
res = response.content

res = res.decode('utf-8')

print(res)
Enter fullscreen mode Exit fullscreen mode

Now our output is a properly formatted string:

<html>
<head>
<title>emdee five for life</title>
</head>
<body style="background-color:powderblue;">
<h1 align='center'>MD5 encrypt this string</h1><h3 align='center'>pV0iSaxkboFU0E07UayP</h3><center><form action="" method="post">
<input type="text" name="hash" placeholder="MD5" align='center'></input>
</br>
<input type="submit" value="Submit"></input>
</form></center>
</body>
</html>


Enter fullscreen mode Exit fullscreen mode

Grabbing specific output

Now it's time to shave our output down to only the text we need. We can use any parsing method, but I found This stack overflow answer to be most helpful.

import requests
response = requests.get('http://104.248.160.75:31480')
res = response.content

res = res.decode('utf-8')

mystr = res
search = "3 align='center'>"
start = mystr.index(search)+len(search)
stop = mystr.index("</h3>", start)
res = (mystr [ start : stop ])

print(res)
Enter fullscreen mode Exit fullscreen mode

Now we have the raw "word."

Now let's hash it!

Hashing the word

According to stack overflow, we can use the following lines to make an MD5 hash of the word:

import hashlib
print(hashlib.md5(res.encode('utf-8')).hexdigest())
Enter fullscreen mode Exit fullscreen mode

Using the following code should yield a valid MD5 hash:

import requests
import hashlib
response = requests.get('http://178.128.167.10:31790')
res = response.content

res = res.decode('utf-8')

mystr = res
search = "3 align='center'>"
start = mystr.index(search)+len(search)
stop = mystr.index("</h3>", start)
res = (mystr [ start : stop ])

print(res)

print("MD5 version:")

print(hashlib.md5(res.encode('utf-8')).hexdigest())
Enter fullscreen mode Exit fullscreen mode

Output should look something like this:

fJHiQK1isKuPYxbEulUH
MD5 version:
80ed60f85b4fbbc982b5816912b1ba6a
Enter fullscreen mode Exit fullscreen mode

Don't forget! We can always verify the validity with an online tool:

Image description

That looks correct! now, we can focus on sending the hashed message back to the server!

Sending the hash

In the original response, we saw that the HTML field name was called "hash" so we'll use that field name to submit our response. After a bit of reading, the syntax became extremely straightforward for the requests library. We just need a dictionary to hold our data and submit our response. With that added, our code now looks like the following:

import requests
import hashlib
# Grabbing and decoding
url = 'http://178.128.167.10:31790'
response = requests.get(url) 
res = response.content
res = res.decode('utf-8')
# Parsing out the word
mystr = res
search = "3 align='center'>"
start = mystr.index(search)+len(search)
stop = mystr.index("</h3>", start)
res = (mystr [ start : stop ])
print(res)

# Hashing as MD5
print("MD5 version:")
hash = (hashlib.md5(res.encode('utf-8')).hexdigest())
print(hash)

# Sending the hash
payload = {"hash":hash}
response = requests.post(url, data=payload)
res = response.content
flag = res.decode('utf-8')
print("\n\n" + flag)
Enter fullscreen mode Exit fullscreen mode

Everything looks ready to use, so let's run it!

Output:

Our flag... Or not?

LSByV3cfj4CH7ufR5G2a
MD5 version:
46b323c4923e460759346454210adb8f


<html>
<head>
<title>emdee five for life</title>
</head>
<body style="background-color:powderblue;">
<h1 align='center'>MD5 encrypt this string</h1><h3 align='center'>OLWB7P9EqGd03jHmmXRN</h3><p align='center'>Too slow!</p><center><form action="" method="post">
<input type="text" name="hash" placeholder="MD5" align='center'></input>
</br>
<input type="submit" value="Submit"></input>
</form></center>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

It seems we're too slow.

I thought we'd be fast enough, but maybe our code was too inefficient. We'll have to find a way to speed it up, but first we'll need to find out how fast we currently are!

Clocking our code

Let's see how fast our code is running.

We can use the time command to clock it

time python3 payload.py yields us:

real    0m0.690s
user    0m0.173s
sys 0m0.017s
Enter fullscreen mode Exit fullscreen mode

Why it didn't work:

After reading a blog post about this challenge, I found out why this wouldn't work properly:

Credit to Soren_codes

Knowing this, I rewrote my code to use a single coherent session rather than sending random disjointed requests.

Our code now looks like this:

import requests
import hashlib
# Grabbing and decoding
url = 'http://161.35.166.224:32511'
session = requests.session()
response = session.get(url) 
res = response.content
res = res.decode('utf-8')
# Parsing out the word
mystr = res
search = "3 align='center'>"
start = mystr.index(search)+len(search)
stop = mystr.index("</h3>", start)
res = (mystr [ start : stop ])
print(res)

# Hashing as MD5
print("MD5 version:")
hash = (hashlib.md5(res.encode('utf-8')).hexdigest())
print(hash)


# Sending the hash
payload = {"hash":hash}
response = session.post(url, data=payload)
res = response.content
flag = res.decode('utf-8')
print("\n\n" + flag)
Enter fullscreen mode Exit fullscreen mode

Only a few small changes, but it made a huge difference!

Output:

C7RrJ4GN4f2tMK51Z8JZ
MD5 version:
d185f72466f92c697b6c9ed3ca496ebe


<html>
<head>
<title>emdee five for life</title>
</head>
<body style="background-color:powderblue;">
<h1 align='center'>MD5 encrypt this string</h1><h3 align='center'>C7RrJ4GN4f2tMK51Z8JZ</h3><p align='center'>HTB{N1c3_ScrIpt1nG_B0i!}</p><center><form action="" method="post">
<input type="text" name="hash" placeholder="MD5" align='center'></input>
</br>
<input type="submit" value="Submit"></input>
</form></center>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Lessons learned

It's times like this that remind me that it's okay to use writeups, even the best people in the field do it to learn!. If I hadn't have stopped and read a writeup, I wouldn't have understood why I needed to use requests.session(), and I wouldn't have been able to progress. It's easy to get frustrated while learning new things, but there's no point in staying frustrated if you're stuck.

Thanks for reading! Be sure to come back to read my writeup on "Heist"!

Image description

Top comments (0)