Nunchucks es una máquina sencilla que explora una inyección de plantilla del lado del servidor (SSTI) basada en NodeJS que conduce a un error de AppArmor que ignora el perfil de AppArmor del binario mientras ejecuta scripts que incluyen el contenido de la aplicación perfilada.
Reconnaissance
Realizaremos un reconocimiento con nmap para ver los puertos que están expuestos en la máquina Nunchucks. Este resultado lo almacenaremos en un archivo llamado allPorts.
❯ nmap -p- --open -sS --min-rate 1000 -vvv -Pn -n 10.10.11.122 -oG allPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-16 22:29 CET
Initiating SYN Stealth Scan at 22:29
Scanning 10.10.11.122 [65535 ports]
Discovered open port 22/tcp on 10.10.11.122
Discovered open port 80/tcp on 10.10.11.122
Discovered open port 443/tcp on 10.10.11.122
Completed SYN Stealth Scan at 22:29, 12.55s elapsed (65535 total ports)
Nmap scan report for 10.10.11.122
Host is up, received user-set (0.051s latency).
Scanned at 2025-02-16 22:29:35 CET for 13s
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
443/tcp open https syn-ack ttl 63
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 12.67 seconds
Raw packets sent: 65535 (2.884MB) | Rcvd: 65542 (2.622MB)
❯ extractPorts allPorts
[*] Extracting information...
[*] IP Address: 10.10.11.122
[*] Open ports: 22,80,443
[*] Ports copied to clipboard
Lanzaremos scripts de reconocimiento sobre los puertos encontrados y lo exportaremos en formato oN y oX para posteriormente trabajar con ellos. En el resultado, comprobamos que se encuentran abierta unas páginas web de Nginx y el servicio de SSH.
❯ nmap -sCV -p22,80,443 10.10.11.122 -A -oN targeted -oX targetedXML
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-16 22:31 CET
Nmap scan report for nunchucks.htb (10.10.11.122)
Host is up (0.065s 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-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to https://nunchucks.htb/
443/tcp open ssl/http nginx 1.18.0 (Ubuntu)
|_http-title: Nunchucks - Landing Page
| tls-alpn:
|_ http/1.1
|_http-trane-info: Problem with XML parsing of /evox/about
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_ssl-date: TLS randomness does not represent time
| 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
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19, Linux 5.0 - 5.14
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 80/tcp)
HOP RTT ADDRESS
1 104.88 ms 10.10.16.1
2 30.95 ms nunchucks.htb (10.10.11.122)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 19.45 seconds
Transformaremos el archivo generado targetedXML para transformar el XML en un archivo HTML para posteriormente montar un servidor web y visualizarlo.
❯ xsltproc targetedXML > index.html
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Añadiremos la siguiente entrada en nuestro archivo /etc/hosts.
Realizamos una enumeración de directorios y archivos a través de feroxbuster y no logramos obtener algún directorio o archivo interesante.
❯ feroxbuster -u https://store.nunchucks.htb/ -t 200 -C 500,502,404 -k
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.11.0
───────────────────────────┬──────────────────────
🎯 Target Url │ https://store.nunchucks.htb/
🚀 Threads │ 200
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
💢 Status Code Filters │ [500, 502, 404]
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.11.0
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🔎 Extract Links │ true
🏁 HTTP methods │ [GET]
🔓 Insecure │ true
🔃 Recursion Depth │ 4
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200 GET 3l 6w 45c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301 GET 10l 16w 179c https://store.nunchucks.htb/assets => https://store.nunchucks.htb/assets/
200 GET 7l 15w 245c https://store.nunchucks.htb/assets/css/fonts.css
200 GET 14l 30w 424c https://store.nunchucks.htb/assets/js/main.js
200 GET 20l 82w 6403c https://store.nunchucks.htb/assets/images/flags/GB.png
200 GET 16l 82w 6002c https://store.nunchucks.htb/assets/images/flags/US.png
200 GET 1566l 2676w 25180c https://store.nunchucks.htb/assets/css/font-awesome.css
Initial Access
Node.js SSTI (Server Side Template Injection)
Realizando diversas pruebas en la página web, el único campo que nos parece interesante es en el cual nos permite indicar nuestro correo electrónico y posteriormente en el output por parte del servidor se imprime el input introducido.
Con lo cual, nos abre la posibilidad de que quizás exista un Template Engine y podamos intentar realizar un SSTI (Server Side Template Injection).
Revisaremos nuevamente las tecnologías de la página web, y comprobamos que utiliza Node.js como lenguaje de programación.
Intentamos realizar una inyección de SSTI básica, pero se nos indica que debemos introducir un correo válido.
Por lo tanto, para intentar eludir esta restricción, interceptaremos la solicitud con BurpSuite. En la solicitud, verificamos que el input y output se encuentran en un formato JSON
Intentamos realizar la siguiente inyección básica de SSTI para comprobar si era vulnerable. En la respuesta por parte del servidor, comprobamos que se ha interpretado la operación y nos ha aparecido el resultado de 7*7, con lo cual todo parece indicar que podemos realizar el SSTI correctamente.
{{7*7}}
En el siguiente blog, se nos mencionan diversas técnicas y payloads para identificar el tipo de Template Engine que nos enfrentamos.
A través del siguiente polyglot payload, intentaremos enumerar el tipo de Template Engine. En este caso, solamente pudimos comprobar que se nos mostraba errores JSON, con lo cual nos hace afirmar que detrás quizás esté Node.js como se nos indicaba en el Wappalyzer.
${{<%[%'"}}%\.
En caso de vulnerabilidad, se puede devolver un mensaje de error o el servidor puede generar una excepción. Esto se puede utilizar para identificar la vulnerabilidad y el motor de plantillas en uso.
Para identificar la vulnerabilidad, se puede seguir la siguiente lista de tareas pendientes:
Detectar dónde existe la inyección de plantillas Identificar el motor de plantillas y validar la vulnerabilidad.
Seguir los manuales del motor de plantillas específico.
Aprovechar la vulnerabilidad
Se puede utilizar la siguiente Cheat Sheet para identificar el motor de plantillas en uso:
Code Execution via SSTI (Node.js Nunjucks)
Realizando una búsqueda sobre Node.js SSTI, nos encontramos con el siguiente blog en el cual mencionan la posibilidad de ejecutar comandos arbitrarios remotos a través de SSTI Node.js Nunjucks.
Realizando una búsqueda por Internet, nos encontramos con el siguiente repositorio de GitHub el cual mediante SSTI en Node.js Nunjucks, logra obtener un RCE.
Inyectaremos el siguiente comando para que se nos muestre el contenido del/etc/passwd. Al enviar la solicitud a través de BurpSuite, en la respuesta del servidor se verifica el contenido del archivo del servidor. Con lo cual, queda confirmada la existencia de poder ejecutar comandos arbitrarios a través del SSTI Node.js.
Por lo tanto, podemos intentar realizar la Reverse Shell para conectarnos al equipo de diferentes maneras. En nuestro caso, para no tener problemas con las ', decidimos verificar si el binario de cURL se encontraba disponible en el sistema objetivo.
A través de la siguiente inyección, se verificó que el binario cURL se encontraba instalado en el equipo.
Por lo tanto, en nuestro equipo local crearemos un script sencillo en Bash para que se ejecute la Reverse Shell, este script lo compartiremos a través de un servidor web.
Verificamos que finalmente logramos obtener el acceso correspondiente al sistema y visualizar la flag de user.txt.
❯ nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.3] from (UNKNOWN) [10.10.11.122] 37010
bash: cannot set terminal process group (993): Inappropriate ioctl for device
bash: no job control in this shell
david@nunchucks:/var/www/store.nunchucks$ cat /home/david/user.txt
d967f92377f2*********************
Al obtener la reverse shell, mejoramos la calidad de la shell con los siguientes pasos para obtener una TTY interactiva.
Attempting to perform Abusing Capabilities (perl) [FAILED]
Revisaremos una comprobación de los grupos y de si disponemos de permisos de sudoers. En este caso, no disponemos de grupos especiales y tampoco podemos comprobar los privilegios sudoers debido que nos requiere proporcionar credenciales del usuario david el cual de momento no disponemos.
david@nunchucks:/var/www/store.nunchucks$ id
uid=1000(david) gid=1000(david) groups=1000(david)
david@nunchucks:/var/www/store.nunchucks$ sudo -l
[sudo] password for david:
Por otro lado, revisamos si había algún binario inusual con privilegios de SUID, no logramos encontrar ninguno. Intentamos también verificar si disponíamos de alguna capabilitie, en el resultado obtenido, nos encontramos la capabilitie /usr/bin/perl = cap_setuid+ep, con la cual podríamos llegar a aprovecharnos para obtener acceso como root.
Revisamos la ubicación del binario perl, accedemos a su directorio y ejecutamos la sintaxis para poder abusar de esta capabilitie, en el primer comando intentamos obtener una Bash como root pero no obtuvimos resultado ninguno.
Intentamos ejecutar el binario para obtener una shell como root, pero no conseguimos una sesión completamente privilegiada. Al ejecutar id, vimos que el UID era root, pero el GID seguía siendo david, lo que impedía elevar nuestros privilegios.
Realizamos una enumeración con linpeas.sh y nos encontramos que AppArmor se encontraba habilitado en el sistema.
AppArmor es un módulo de seguridad del kernel de Linux que puedes utilizar para restringir las capacidades de los procesos que se ejecutan en el sistema operativo host. Cada proceso puede tener su propio perfil de seguridad.
Por otro lado, también volvemos a verificar la existencia de la capabilitie mencionada.
Al revisar la documentación sobre AppArmor, encontramos información sobre su funcionamiento y la ubicación donde se definen las políticas y restricciones de los binarios. Al analizar /etc/apparmor.d/, detectamos un perfil asociado a /usr/bin/perl, lo que podría limitar su uso en la explotación.
david@nunchucks:/etc/apparmor.d$ ls -l
total 56
drwxr-xr-x 4 root root 4096 Oct 28 2021 abstractions
drwxr-xr-x 2 root root 4096 Oct 28 2021 disable
drwxr-xr-x 2 root root 4096 Oct 28 2021 force-complain
drwxr-xr-x 2 root root 4096 Oct 28 2021 local
-rw-r--r-- 1 root root 1313 May 19 2020 lsb_release
-rw-r--r-- 1 root root 1108 May 19 2020 nvidia_modprobe
-rw-r--r-- 1 root root 3222 Mar 11 2020 sbin.dhclient
drwxr-xr-x 5 root root 4096 Oct 28 2021 tunables
-rw-r--r-- 1 root root 3202 Feb 25 2020 usr.bin.man
-rw-r--r-- 1 root root 442 Sep 26 2021 usr.bin.perl
-rw-r--r-- 1 root root 672 Feb 19 2020 usr.sbin.ippusbxd
-rw-r--r-- 1 root root 2006 Jul 22 2021 usr.sbin.mysqld
-rw-r--r-- 1 root root 1575 Feb 11 2020 usr.sbin.rsyslogd
-rw-r--r-- 1 root root 1385 Dec 7 2019 usr.sbin.tcpdump
Al revisar el perfil de AppArmor en /etc/apparmor.d/usr.bin.perl, observamos que /usr/bin/perl tiene la capacidad setuid, lo que le permite cambiar el UID del proceso. Sin embargo, existen restricciones clave que limitan su alcance:
Se deniega el acceso de escritura y ejecución a /root/* y /etc/shadow.
No se permite la lectura de /etc/nsswitch.conf.
Se permite la ejecución controlada de algunos binarios como /usr/bin/id, /usr/bin/ls, /usr/bin/cat y /usr/bin/whoami.
Se restringe el acceso de /usr/bin/perl a ciertos archivos críticos, pero se permite la lectura en /home/ y /home/david/.
Estas reglas limitan el impacto de la capabilitysetuid, aunque aún es posible evaluar si existen formas de evasión para escalar privilegios.
Investigando en Internet, encontramos un blog donde explicaban cómo realizar un bypass de AppArmor usando un script en Perl. Siguiendo este método, creamos un script en /tmp/gzzcoo.pl, le asignamos permisos de ejecución y lo ejecutamos.
Inicialmente, al ejecutar perl gzzcoo.pl, el sistema devolvió un error de Permission denied. Sin embargo, al ejecutarlo directamente (./gzzcoo.pl), logramos obtener una shell como root y acceder a la flag root.txt.
Este comportamiento indica que AppArmor restringe la ejecución de Perl directamente, pero al ejecutar el script como binario, logramos evadir la restricción y escalar privilegios a root.
A través de la herramienta de , la utilizaremos para extraer los puertos del archivo que nos generó el primer escaneo a través de Nmap. Esta herramienta nos copiará en la clipboard los puertos encontrados.
Accederemos a y verificaremos el resultado en un formato más cómodo para su análisis.
Accederemos a y nos encontramos con la siguiente página web, en la cual en una enumeración básica, no logramos obtener resultado relevante.
Disponemos en signup una página de registro de usuarios. Al intentar registrarnos como un nuevo usuarios, se nos indicaba que no podíamos realizar dicha acción.
Accedemos a y nos encontramos con la siguiente página web.
A través dela herramienta de , revisamos la manera de abusar de esta capabilitie que disponemos.