sábado, 5 de agosto de 2017

WordPress: Role-Based Database Connection Strings

Una aplicación web, o un framework CMS como WordPress, utiliza un repositorio de datos en un motor de bases de datos, en concreto MySQL. Para eso, durante el proceso de instalación se crea un usuario del motor de bases de datos que es el que tiene el control de todas las tablas dentro de la base de datos y puede hacer con ellas lo que le plazca. Es decir, puede insertar, modificar o borrar registros en todas y cada una de las tablas sin ninguna limitación.

Las acciones que ese usuario de MySQL realiza dentro de ellas, como por ejemplo dar de alta un nuevo registro mediante una instrucción INSERT que represente a un nuevo usuario del CMS, están limitadas por el código de la propia aplicación, es decir, el código PHP del motor WordPress.

Esta es una situación muy habitual en todas las aplicaciones web, y en especial en la mayoría de los frameworks de Internet, y tiene implicaciones en la seguridad porque, si un atacante es capaz de encontrar un bug de SQL Injection en cualquiera de los códigos de WordPress, ya sea en el core del framework, en un plugin o en un tema, implicaría directamente el control de todas las tablas y su contenido que están en MySQL. En èsta charla de Hardening Wordpress Like a Hacker se explica en detalle.


Figura 2: Hardening WordPres like a Hacker

Esto se debe a que WordPress no utiliza un sistema de Role-Based DB Connection Strings, es decir, que todos los usuarios de WordPesss - ya sea un usuario anónimo o el administrador - utilizan la misma cuenta de MySQL en la cadena de conexión para ejecutar las consultas SQL, algo que debería evitarse en un entorno fortificado.

Aunque lo suyo es que cada usuario de la aplicación web tuviera su representación en un usuario de la base de datos, a veces por gestión de cuentas volátiles, por licencias en algunos modelos de venta de algunos motores de base de datos, por la implicación que cuentas del motor puedan tener dentro del resto del sistema informático - por ejemplo, motores integrados en Active Directory - o por complejidad en el desarrollo no se hace.  En esos casos, habría que diseñar un modelo de Role-Based Database Connection Strings.

Se deben reconocer los roles principales de la aplicación, en este caso del motor de WordPress, y crear un usuario en MySQL por cada uno de esos roles. Después, se deben entregar permisos sobre las tablas a cada uno de esos usuarios teniendo en cuenta que solo deben obtener acceso a lo estrictamente necesario para el cumplimiento de su rol.

Figura 3: Esquema de Role-Based Database Connections

Después, cuando se produce el proceso de login de un usuario de WordPress en el framework, el sistema debe ser capaz de reconocer su rol en WordPress y ejecutar las consultas SQL al motor MySQL con una DB Connection que haya utilizado el usuario adecuado de su rol, consiguiendo limitar el impacto que pueda tener un posible bug de SQL Injection que fuera descubierto en un plugin, un tema o en el core del sistema.

Figura 4: Cuando sea un usuario loggado se utiliza un usuario privilegiado en MySQL

Como prueba de concepto, se hace una modificación al sistema de conexiones a la base de datos para que el framework diferenciara algo muy básico: Entre un usuario de WordPress que ha hecho login, y un visitante anónimo que no ha hecho login en WordPress.

Figura 5: Cuando sea un usuario anónimo se utiliza un usuario sin privilegios en MySQL

De esta forma, cuando se lance una consulta al motor MySQL esta utilizará un usuario distinto de MySQL, siendo el segundo un usuario sin ningún privilegio de INSERT, UPDATE o DELETE en las tablas que WordPress utiliza en MySQL.

Figura 6: Definición de distintas cadenas de conexión

El funcionamiento es muy sencillo, cuando se va a realizar la conexión a MySQL desde WordPress, observamos si el usuario está logado o no en el framework y se elige uno u otro usuario de MySQL para tirar la cadena de conexión.

Figura 7: Comprobación de si usuario está logado o no en la PoC

Este vídeo de aquí enseña cómo funciona en la prueba de concepto.


Figura 7: WordPress Role-Based Database Connection Strings to MySQL