Blue Core Research
Contactanos
Detección de Ataques en WordPress
WordPress es una aplicación común para gestionar sitios web. Pero esta historia trata sobre cómo detectamos un ataque a una aplicación genérica.

Un domingo al mediodía, recibí un alerta sobre una anomalía. Era 19 de marzo de 2023. Esta historia es sobre lo que sucedió.

Antecedentes

El sitio web de Blue Core Research usa WordPress (sistema libre y de código abierto de gestión de contenidos). WordPress usualmente usa MySQL como base de datos de backend, y nuestra instalación no es diferente.

Mientras nuestro WordPress no contiene información sensible, aún lo protegemos con Core Audit. Parcialmente, lo hacemos porque producimos Core Audit, y las licencias no nos cuestan nada. Pero para contextos más grandes, protegemos esta base de datos porque nuestro sitio web es la cara de la compañía, y aún sin información sensible, una filtración dañaría nuestra reputación.

Como verás en este trabajo, protegiendo la base de datos proteges la aplicación (WordPress) también. Y eso defiende nuestro servidor de ataques en Internet.

La Anomalía

Nuestra instalación de Core Audit cuenta con una configuración relativamente simple con alertas diarias de detección de anomalías. Recibimos algunos falsos positivos cada tanto, pero una mañana de domingo del 19 de marzo de 2023, recibimos un alerta de un nuevo error.

Access denied for user ''@'' (using password: YES)

Eso inmendiatamente me levantó una bandera roja. Esto es porque las anomalías solo alertan sobre algo diferente, como un cambio en la actividad del perfil de la aplicación. Pero un cambio que causa un acceso denegado parece sospechoso.

La Investigación

Las anomalías de Core Audit descansan en el repositorio de seguridad de Core Audit. Y esta anomalía particular está basada en la reducción de la porción de SQL de ese repositorio. El repositorio reducido SQL contiene cada construcción SQL que la base de datos ejecuta con la resolución de 5 minutos.

Una vez que recibí el alerta, me logué en Core Audit y revisé la vista relevante forense. Rápidamente encontré sobre qué fui alertado:

Date:     Sat 2023/03/18
Time:     18:55 - 19:00
Count:    1 per 5 minutes
Rows:     0
Command:  ERROR TEXT
Activity: Access denied for user ''@'' (using password: YES)

Esto es un error interno MySQL resultante de un log in fallido. El usuario y anfitrión en este error están entre comillas simples (‘) y son, por lo tanto, despojados desde el repositorio reducido de SQL. La división de literales es parte de cómo opera el repositorio reducido de SQL.

Mi próxima parada fue para buscar la sesión fallida que la causó. Al alternar a la sesión de vista forence, encontré esta sesión:

Start:    2023/03/18 18:55:59
End:      2023/03/18 18:55:59
Type:     No Login
Username: username_here
Machine:  localhost

Esto luce inusual desde que no contamos con un usuario en la base de datos llamado username_here Esto es, obviamente, un usuario inválido. Mi próxima parada fue mirar los logs del web server para ver quién o qué disparó este login inusual.

Aquí hay un extractro del log de Apache:

[18:55:36] GET /.wp-config.php_copy
[18:55:38] GET /.wp-config.php.rar
[18:55:39] GET /.wp-config.php.7z
[18:55:41] GET /.wp-config.php.tmp
[18:55:42] GET /.wp-config.php_tmp
[18:55:44] GET /.wp-config.php.old
[18:55:46] GET /.wp-config.php.0
[18:55:47] GET /.wp-config.php.1
[18:55:49] GET /.wp-config.php.2
[18:55:50] GET /.wp-config.php.zip
[18:55:52] GET /.wp-config.php.gz
[18:55:53] GET /.wp-config.php~
[18:55:55] GET /wp-config.php.templ
[18:55:56] GET /wp-config.php1
[18:55:58] GET /wp-config.php2
[18:55:59] GET /wp-config-sample.php
[18:56:00] GET /wp-config-backup.txt
[18:56:02] GET /wp-config.php.orig
[18:56:03] GET /wp-config.php.original
[18:56:05] GET /wp-license.php?file=..%2F..
[18:56:06] GET /wp-config.save
[18:56:07] GET /wp-config.txt
[18:56:09] GET /wp-config.dist
[18:56:10] GET /.wp-config.php.swo
[18:56:12] GET /wp-config%20copy.php
[18:56:12] GET /wp-config_good
[18:56:14] GET /wp-config-backup
[18:56:15] GET /wp-config-backup.php
[18:56:16] GET /wp-config-backup1.txt
[18:56:18] GET /wp-config-good
[18:56:19] GET /wp-config-sample.php.bak
[18:56:21] GET /wp-config-sample.php~
[18:56:22] GET /wp-config.backup

El culpable es claramente wp-config-sample.php, y mirando dentro de él, podemos encontrar estas líneas:

define( 'DB_USER', 'username_here' );
define( 'DB_PASSWORD', 'password_here' );
…
require_once ABSPATH . 'wp-settings.php';

Ahora entendemos qué pasó: alguien escaneó el sitio web buscando vulnerabilidades y llamó wp-config-sample.php. Ese script PHP contiene un usuario y contraseña inválido que disparó una falsa conexión a la base de datos. Core Audit detectó este inusual comportamiento y elevó una alerta.

WordPress?

Aunque muchos no consideran que WordPress sea un buen ejemplo de seguridad de aplicaciones, nosotros creemos que es valioso por varios factores importantes:

Terceros y cadena de suministro

En primer lugar, WordPress es una aplicación 100 % de terceros. No la hemos programado, no hemos revisado el código fuente y casi no tenemos conocimiento del código, el modelo de datos ni ningún otro aspecto de esta aplicación.

Al ser un software de código abierto, WordPress está expuesto tanto a vulnerabilidades que los hackers pueden descubrir en el código fuente como a ataques a la cadena de suministro.

Para empeorar las cosas, los sitios web de WordPress casi siempre utilizan plugins. Gran parte del poder de la plataforma WordPress reside en su extensibilidad gracias a las decenas de miles de plugins que existen. El uso de plugins amplía significativamente la superficie de ataque del software de terceros y de la cadena de suministro. Los plugins suponen una gran cantidad de código adicional desconocido de múltiples proveedores o desarrolladores, diferentes estándares de codificación, mejoras en el modelo de datos con más tablas y mucho más.

En otras palabras, WordPress es lo que se podría considerar un ejemplo extremo de aplicación de terceros y protegerlo es más difícil que la mayoría de las demás aplicaciones.

SQL dinámico

WordPress lleva el concepto de SQL dinámico al extremo. No solo todos los SQL incorporan literales, sino que a menudo se generan dinámicamente con cláusulas «where» creadas sobre la marcha en función de la entrada del usuario.

El reto no son solo los ataques SQL dinámicos, sino también el amplio vocabulario SQL, que hace imposible predecir todas las combinaciones SQL que WordPress puede generar.

Una vez más, los plugins agravan el problema debido a un vocabulario SQL aún mayor y desconocido, y a más vulnerabilidades potenciales en el código que genera esos SQL dinámicos.

Popular y con presencia en Internet

WordPress es muy popular y es una aplicación con presencia en Internet. Por lo tanto, los hackers tienen un gran incentivo para encontrar vulnerabilidades. Aprovechar estas vulnerabilidades también puede ser fácil, ya que Internet está lleno de sitios web de WordPress con poca o ninguna seguridad adicional.

En resumen: proporcionamos una defensa eficaz a una aplicación grande, dinámica y extensible como WordPress sin depender de vulnerabilidades conocidas ni de las características específicas de la aplicación.

Resolución

En WordPress, wp-config-sample.php es parte del paquete de instalación de WordPress. El proceso de instalación de WordPress copia este archivo en wp-config.php y define algunos parámetros como el usuario y contraseña de la base de datos.

Por lo tanto, wp-config-sample.php es esperado que exista en una instalación de WordPress. Y si el equipo de desarrollo de WordPress ha hecho bien su trabajo, es probable que no signifique una filtración de WordPress al llamarlo así.

Pero como todos sabemos, los errores existen, y ataques 0-dia pueden siempre ocurrir. Teniendo este archivo alrededor parece preguntar por problemas. Este archivo no tiene otro propósito en WordPress que no sea como plantilla para wp-config.php, entonces ¿no deberías eliminarlo?

Esto nos lleva a otro comportamiento de WordPress: su actualización. Cuando WordPress actualiza, sobre escribe todos los archivos que son parte del paquete de WordPress. Por lo tanto, borrando wp-config-sample.php será desecho tan pronto como WordPress automáticamente actualice.

Otra opción es dejar el archivo en el lugar pero cambiar los permisos del archivo así Apache no puede acceder ahí. Esto prevendría este script PHP de ejecutarse. Como sea, esto tal vez cause errores cuando WordPress intenta actualizar porque no será capaz de sobre escribir el archivo. Entonces la actualización requiere intervención manual.

Por ejemplo, puedes eliminar permisos ejecutando:

<Files ~ "wp-config-sample.php">
deny from all
</Files>

Más allá

Como expliqué previamente, wp-config-sample.php es usado para crear wp-config.php durante la instalación. Esto significa que wp-config.php puede ser también vulnerable al mismo ataque u otro similar ataque 0-dia.

Más problemático es si una actualización de WordPress arregla una vulnerabilidad en wp-config-sample.php, este arreglo no actualizará wp-config.php desde que ese copy nunca es modificado.

wp-config.php está pensado para ser incluido por otros archivos de WordPress como index.php. Luego de definir los parámetros de la conexión de la base de datos, el script llama wp-settings.php para configurar el ambiente WordPress, incluyendo la conexión a la base de datos.

En otras palabras, wp-config.php nunca quiere ser ejecutado directamente. Para protegerlo contra un ataque ejecutado directamente, podemos agregar una línea en la parte de superior de wp-config.php para detener el proceso.

if (get_included_files()[0] == '/path_to_site/wp-config.php') exit();

Ideas finales

A pesar de estos desafíos, los análisis de anomalía de Core Audit proveen seguridad efectiva así como tiene un razonable nivel de falsos positivos y, en este caso, ha sido alertado de un ataque contra la aplicación.

Es importante notar que Core Audit no tiene un soporte especial para PHP o WordPress. Tampoco miramos ninguna vulnerabilidad en particular en la base de datos o la aplicación. Solo teníamos un objetivo general de detección de anomalía que nos alertó tan pronto como la aplicación se comportó diferente. Esto fue suficiente para identificar un ataque.

Como has visto, monitorear cambios en el perfil de la actividad de la base de datos de la aplicación nos permite detectar muchos cambios en el comportamiento de la aplicación. Mientras algunos cambios ocurren naturalmente, otros indican un problema de seguridad o un ataque.

No posts found

Si tenes alguna pregunta o comentario, no dude en hacérnoslo saber. Estaremos encantados de escucharles