Currently working as a Senior Consultant at Netcompany spending my full-time job solving the SharePoint riddles. In the free time I'm expanding my understanding of cybersecurity through hacking activities. Git fanboy.
">
It's been a while since I have participated in HackTheBox Capture The Flag event. The platform got a really nice, fresh look to it.
Web
Evaluation Deck
A powerful demon has sent one of his ghost generals into our world to ruin the fun of Halloween. The ghost can only be defeated by luck. Are you lucky enough to draw the right cards to defeat him and save this Halloween?
JavaScript game with Python backend - flip the cards to deal damage or heal monster, depending on the dynamic HTML attributes of the card DOM elements. After 8 tries, you can restart the game by refreshing the page.
At first, I thought that to get the flag, I have to intercept the request when card got flipped and change the damage value to kill the ghost with one hit. That was not the case. No additional field in response.
After unziping the source code, in the challenge/application/blueprints/routes.py there was a vulnerable code with potential of RCE.
Basically, the code here executes as it was directly executed in python shell. So..
Python expressions are executed from left to right, can be separated by semicolon. The flag was obtained by sending a modified request (here I'm using Burp, but that doesn't matter). To insert the output of a system command, I've used the os.popen(..).read() expression.
An unknown entity has taken over every screen worldwide and is broadcasting this haunted feed that introduces paranormal activity to random internet-accessible CCTV devices. Could you take down this streaming service?
Poke the /api/register endpoint to see if it is injectable..
..and it is. Because I'm going to insert values directly into database, I'm encoding the 1234 phrase using the code from challenge/application/utilpy ($2b$12$ZcQbtfnbG2x16HZDJyYN.O9lVunjQo4A5wSBtoNIThsaCtBmsS9qy).
defgenerate_password_hash(password):
salt = bcrypt.gensalt()
return bcrypt.hashpw(password.encode(), salt).decode()
Unfortunately, I can't execute more than one command before committing beforehand.
Because this happens outside my control and I can't do it by myself, I'm stuck with one command. There is however, a way to force change password for admin by using MariaDB/MySQL extensionINSERT ON DUPLICATE KEY UPDATE. This way I can update the admin row regardless of its presence in the database.
{"username":"admin\",\"$2b$12$jSXUhVnIZ8eHQbynD1y1TuZL7oMVevF8ORjYwQCFGlN0RbRgnf9Ei\") ON DUPLICATE KEY UPDATE password=\"$2b$12$jSXUhVnIZ8eHQbynD1y1TuZL7oMVevF8ORjYwQCFGlN0RbRgnf9Ei\"#","password":"1234"}
After sending the payload, I'm receiving success message on registering account and I can login as admin and read the flag.
There's a new trend of an application that generates a spooky name for you. Users of that application later discovered that their real names were also magically changed, causing havoc in their life. Could you help bring down this application?
By exploring the attached source files, point of exploitation is established to spookify(text) method or more specifically the Template(result).render():
Further message proves the Mako templates RCE vulnerability over context-free payloads (running os.system(..) function).
Worth noting that payload creation could be impossible (or significantly harder) if font4 would not passthrough non-alfanumeric characters. Here are the steps that leads me to reading the flag.
Pwn
Pumpkin Stand
This time of the year, we host our big festival and the one who craves the pumpkin faster and make it as scary as possible, gets an amazing prize! Be fast and try to crave this hard pumpkin!
Given: Docker address + binary Difficulty: easy
I have serious lacks in binary exploitation, so for me that was almost pure luck. I have launch Ghidra and opened the binary file.
In main, there was a multiple while(true) statements and the command reading the flag was past the loops scope. So, the way to get the flag could be to either jump outside the loops by using some overflow mechanics and overwriting the jump pointer on stack or heap.. or by meeting the break condition. I'm choosing the second option.
I did notice that almost none of the inputs are validated, only pumpcoins value (but also, not so smart). So, I started experimenting by entering different values on the first screen because of the highlighted expression (it takes the number given by the user and multiplies it, before subtracting from the pumpcoins). That way, I was able to determine the correct values for breaking out of the while loops.
After months of research, you're ready to attempt to infiltrate the meeting of a shadowy cult. Unfortunately, it looks like they've changed their password!
Given: Docker address + binary Difficulty: easy
I would be surprised if there are quicker way to solve this challenge. Also good reminder to always start with low hanging fruits - like running strings over the file.
$ strings meeting
#among other strings
sup3r_s3cr3t_p455w0rd_f0r_u!
Then used that passphrase on the Docker hosted binary to get the shell and cat the flag.
Encoded Payload
Buried in your basement you've discovered an ancient tome. The pages are full of what look like warnings, but luckily you can't read the language! What will happen if you invoke the ancient spells here?
Well, as always, start with low hanging fruits.
chmod +x encodedpayload
strace ./encodedpayload
Ghost Wrangler
Who you gonna call?
As you can see, the flag is written to the buffer, and then it is overwritten by the text. So the solution is to debug the binary and put the breakpoint at main, execute instructions step by step.
gdb ./ghost
break main
run
nexti
...
# repeat nexti watching the registers
Ouija
You've made contact with a spirit from beyond the grave! Unfortunately, they speak in an ancient tongue of flags, so you can't understand a word. You've enlisted a medium who can translate it, but they like to take their time...
Pretty straightforward, but requires some C++ programming knowledge and usage of some disassemble tool like ghidra.
Open with ghidra, copy disassembled main (only fragment with code). Declare variables, include headers, clear sleeps, replace last print character by character with putting into previously declared array of chars, and after the loop print the flag.