Emdee five for life Writeup
14 December 2022 #CTF #HTB #chall #easy #miscFirst Look
After launching the instance, we have access to a simple web page:
One quick note: MD5 is actually a hashing algorithm, which is different from an encryption algorithm. 🤓
With that being said, let's do it:
$ echo 5rO1gBWPq6pTRDoxxfwL | md5sum
ebada27ff4b872dcb076cf75304a5e69 -
But when we submit it, it says we are too slow:
:(
Automation
We may be too slow, but our computer isn't. That's why we will automate the process using python.
Get random string
The first step is to get the string we have to hash:
import requests
url = 'http://157.245.35.145:31538'
r = requests.get(url)
print(r.text)
Let's execute it:
$ python chall.py
<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'>NYdJS0qhLeRNznBsNadK</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>
As we can see it works, but we just want the random string, not the whole HTML...
We could do some regex magic to extract the string we want but there is a much better (and easier) solution: BeautifulSoup (yeah weird name, I know).
pip install beautifulsoup4
to install it if it isn't already.
Firstly, we should look at the source of the page to see how we'll parse out the random string:
It is inside a <h3>
tag. That's what we'll use.
Let's update our script:
import requests
from bs4 import BeautifulSoup
url = 'http://157.245.35.145:31538'
# get random string to hash
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html.parser')
to_hash = soup.find('h3').string
print(to_hash)
We feed r.text
to BeautifulSoup which is the raw HTML of the response, then we use the find()
function to get the first occurence of a <h3>
tag. The string
attribute contains only what's inside of this tag.
Let's see if it works:
$ python chall.py
9UN0MihEQmpH3y2cXDnJ
It does!
Hash string
The next step is to hash this string. We'll use the hashlib module to do that:
import requests
from bs4 import BeautifulSoup
import hashlib
url = 'http://157.245.35.145:31538'
# get random string to hash
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html.parser')
to_hash = soup.find('h3').string
# use MD5 to hash the string
hashed = hashlib.md5(to_hash.encode()).hexdigest()
print(hashed)
The md5
function wants bytes as parameter, so we encode()
the random string first. hexdigest()
returns the hexadecimal representation of the hash.
Here we go again:
$ python qwe.py
81ae42a25f0b7f0cd919668ab27b96c7
Nice.
POST hashed string
The final step is to actually send the hashed string to the server and get our well deserved flag.
But before that, we need to know how we should send it. We can once again take a look at the HTML of the page:
Here we see the input field in which we enter the hash has its 'name' attribute set to 'hash'. This value will be used as the parameter name in the POST request.
Let's update our script one more time:
import requests
from bs4 import BeautifulSoup
import hashlib
url = 'http://157.245.35.145:31538'
# get random string to hash
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html.parser')
to_hash = soup.find('h3').string
# use MD5 to hash the string
hashed = hashlib.md5(to_hash.encode()).hexdigest()
# send POST request to submit the hashed string
r = requests.post(url, data={'hash': hashed})
soup = BeautifulSoup(r.text, 'html.parser')
flag = soup.find('p').string
print(flag)
We simply use requests.post
to perform the POST request and we specify the 'hash' parameter in data
as a dictionary. BeautifulSoup is used again to display the content of the paragraph that says if we are too slow (for fun).
$ python chall.py
Too slow!
What? Too slow? How? If we take a closer look at the website, we can see a cookie is set:
The random string might be linked to the session (and the cookie, by extension) so we need to use the same as the one we got with the first request (just a wild guess, I don't actually know).
We can use requests.session()
to take care of that (it will send the cookie for us).
We'll edit the script one last time (i swear):
import requests
from bs4 import BeautifulSoup
import hashlib
url = 'http://157.245.35.145:31538'
s = requests.session()
# get random string to hash
r = s.get(url) # start a session
soup = BeautifulSoup(r.text, 'html.parser')
to_hash = soup.find('h3').string
# use MD5 to hash the string
hashed = hashlib.md5(to_hash.encode()).hexdigest()
# send POST request to submit the hashed string
r = s.post(url, data={'hash': hashed}) # reuse the existing session
soup = BeautifulSoup(r.text, 'html.parser')
flag = soup.find('p').string
print(flag)
We just replaced requests.get
and requests.post
by s.get
and s.post
to use our session object.
This time we should be good:
$ python chall.py
HTB{N1c3_ScrIpt1nG_B0i!}
Key Takeaways
- Use BeautifulSoup to parse HTML
- Use
requests.session()
to reuse cookies (and other settings)