Minimizando problemas con iSQL en WordPress

29 Ago

Alrededor del 15% de las vulnerabilidades de WordPress y sus plugins son del tipo iSQL (ver https://www.keycdn.com/blog/wordpress-security/) Este tipo de problemas adquiere mayor importancia debido a que, por defecto, la conexión entre WordPress y la base de datos que sustenta nuestro servicio se realiza, independientemente del tipo de usuario que se conecta (usuario del servicio), con la misma conexión (es decir, con el mismo usuario -de la base de datos-  y, por tanto, permisos en dicha base de datos).

Una máxima de seguridad es otorgar los privilegios estrictamente necesarios para realizar la tarea solicitada, ni más, ni menos. Como podemos observar en esta entrada (https://ayudawp.com/como-wordpress-utiliza-mysql/) WordPress dispone de diversas tablas, cada una para almacenar un tipo de información, que le permiten realizar todas las tareas asociadas a su funcionalidad como CMS . Para mejorar la seguridad de nuestro sistema aplicando el principio de mínimo privilegio, debemos tener en cuenta que en un uso normal, el usuario de la base de datos no necesitará cambiar la estructura ni tipo de permisos de la propia base de datos, solo gestionar los datos almacenados, por lo que lo primero que podemos hacer es proporcionarle exclusivamente los permisos de gestión de datos:

GRANT SELECT , INSERT , UPDATE , DELETE ON  `[DATABASE]` . * TO  ‘[USER]’@'[HOST]’;

donde DATABASE es el nombre de la base de datos de nuestro WordPress en el motor de base de datos que usemos (MySQL, María,…), USER el usuario de conexión y HOST el equipo desde el que establecemos la conexión (usualmente, localhost)

Por otra parte, cuando actualicemos la versión de WordPress o algún plugin sí que debemos tener permisos para cambiar la estructura de la base de datos.  Además, solo los usuarios autenticados escribirán alguna vez en la base de datos: por ejemplo para publicar entradas o comentarios (si no permitimos que los NO autenticados publiquen comentarios, por supuesto) o cambiar la contraseña; por lo que para los NO autenticados, el usuario de conexión a la base de datos debería tener SOLO permisos de lectura.

Este razonamiento nos lleva a que, para garantizar el principio de mínimo privilegio (e, incluso, el de mínima exposición) debemos disponer de diferentes usuarios de la base de datos para utilizar en diferentes tipos de conexión con el objetivo de que cada usuario disponga de los permisos adecuados a las necesidades del momento.

¿Cómo podemos disponer de varias conexiones en WordPress?

Modificando los ficheros:

  1. wp-config.php para definir los usuarios de la base de datos y sus contraseñas de acceso (necesitamos definir tantas variables equivalentes a DB_USER y DB_PASSWORD como usuarios con distintos perfiles necesitemos)
  2. wp-includes/load.php, en concreto, la función  requiere_wp_db() para añadir un código PHP cuyo objetivo sea generar una conexión con el usuario de la base de datos apropiado en función de si está el usuario -del WordPress– identificado o no (lo estará siempre que exista la cookie cuyo nombre sigue este patrón ‘wordpress_logged_in*’) y, en el caso de estarlo, que sea el administrador del sitio (el contenido de la cookie indica el usuario). La conexión que, por defecto, tiene esta función es:

$wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );

En nuestro caso, tras las comprobaciones pertinentes, DB_USER y DB_PASSWORD deberían ser las definidas en el paso 1 para los “otros” usuarios.

Por último (o lo primero a realizar, da igual) debemos crear los usuarios con la contraseña y los permisos adecuados en la base de datos. Para el ejemplo, 3 para estas 3 situaciones y permisos:

  • Para usuarios NO autenticados, crearemos un usuario de la base de datos de solo lectura (es decir, permisos para SELECT)
  • Para usuarios autenticados que no sean el administrador, crearemos un usuario con  permisos de gestión de datos: SELECT, INSERT, DELETE y UPDATE
  • Para el usuario administrador: el que ya trae WordPress por defecto que permite todo.

Con estas tareas, en el caso de sufrir un ataque iSQL, podemos minimizar problemas o, directamente, no tenerlos si no están implicados usuarios autenticados.

¡Espero que os sea útil!

PD: ¡Cuidado con los cambios que hacéis en la base de datos y en los ficheros mencionados! No haced los cambios directamente en el entorno que tengáis en producción, por si acaso, y además, tened copias de seguridad.

PD2: Este es un ejemplo sencillo con 3 perfiles, pero podemos incluir todos los que consideremos. Por ejemplo, podríamos distinguir entre perfiles de usuario de WordPress (subscriptor, editor, etc ) definiendo para cada uno de ellos un usuario de la base de datos con los permisos por tabla estrictamente necesarios de tal forma que, por ejemplo, tabla a la que un perfil de usuario no tenga que acceder (wp_options para subscriptores), tendrá prohibido el acceso a ella.