Seguridad y gestión de los usuarios
Introducción
La seguridad de los datos del sistema informático de la empresa no es solo responsabilidad del RSSI (Responsable de la Seguridad de los Sistemas de Información). Los técnicos y las buenas prácticas necesarias para protegerse deben ser conocidas y aplicadas por cualquier persona. Los elementos de la cadena de aplicaciones son interdependientes; la fortaleza de esta cadena va a depender de la solidez del eslabón más débil. Una prueba no efectuada por la aplicación, una cuenta de usuario que tenga demasiados derechos sobre la base de datos, una actualización de seguridad no efectuada o simplemente una torpeza en el servidor de producción pueden ser la causa del robo o deterioro de los números de tarjetas bancarias de sus clientes, por ejemplo. Las consecuencias pueden ser desastrosas tanto financieramente como en términos de imagen para la empresa. Si bien la seguridad absoluta no existe, vamos a tratar de mostrar todas las prácticas necesarias para minimizar los riesgos en este capítulo.
Securización del servidor MySQL
Las cuestiones relacionadas con la seguridad deben plantearse desde la instalación del servidor de base de datos. En la filosofía de MySQL, el usuario debe poder descargar, instalar y utilizar el SGBDR (Sistema de Gestión de Bases de Datos Relacionales) sin ninguna dificultad. Esta simplicidad es uno de los puntos fuertes de MySQL, ya que, por un lado, esto permitió democratizar el uso de una base de datos haciendo accesible este universo (muchos desarrolladores han experimentado las bases de datos mediante MySQL) y, por otro, esto da la posibilidad de probar fácilmente una aplicación. El inconveniente principal es que la instalación predeterminada es muy permisiva, sobre todo en materia de seguridad...
1. Securización de la instalación
El objetivo de esta sección no es volver a la instalación del servidor que se detalla en el capítulo Instalación del servidor, sino recordar algunos puntos cruciales en materia de seguridad, que deberá adaptar en función del tipo de instalación y de su sistema operativo.
a. Controlar los permisos
Debemos crear un grupo y un usuario dedicado para iniciar la instancia mysqld:
$ groupadd mysql
$ useradd -g mysql mysql
El directorio de datos contiene información sensible; por tanto, debe preservarse de actos dolosos o de la visualización por personas no autorizadas.
$ cd /usr/local/mysql/
$ chown -R root .
$ chown -R mysql data
$ chgrp -R mysql .
mysqld no debe, en ningún caso, ejecutarse con el administrador del sistema root en UNIX (o administrador con MS Windows). Un usuario con, por ejemplo, el derecho FILE puede crear archivos como root.
b. Poner contraseña a la cuenta root
Es el superusuario de MySQL (no confundir con el administrador del sistema root bajo UNIX). Cuenta, por lo tanto, con todos los derechos sobre el servidor. Debe protegerse mediante contraseña. Esto es válido para cualquier sistema operativo.
$ mysql -u root # conexión al servidor con el usuario root sin
contraseña
mysql> SET PASSWORD FOR root@localhost = password('m0T2p4ss3'); /*
el comando set password permite implementar una contraseña para una
cuenta de usuario */
Como veremos un poco más adelante, un usuario MySQL está compuesto...
Cifrado de datos
Para hacer frente a las necesidades de cifrado de información sensible (financiera, médica...) o para tratar de protegerse contra el robo de datos, contra administradores poco escrupulosos, puede ser necesario encriptar los datos. Antes de la versión 5.7, MySQL carecía de módulos criptográficos capaces, por ejemplo, de encriptar el contenido de una columna o de una tabla. Sin embargo, podemos cifrar/descifrar los datos con las funciones MySQL AES_ENCRYPT()/AES_DECRYPT(), DES_ENCRYPT()/DES_DECRYPT() y ENCODE()/DECODE() (para más detalles, consulte la página siguiente: https://dev.mysql.com/doc/refman/5.7/en/encryption-functions.html).
Los datos son entonces cifrados en el disco. Sin embargo, están en texto claro, incluida la clave de cifrado en el código SQL, así como en la red.
mysql> INSERT INTO t_crypt VALUES (1, AES_ENCRYPT('Frase cifrada',
'crypt_key'));
Query OK, 1 row affected (0,00 sec)
mysql> SELECT i, b FROM t_crypt;
+------+------------------+
| i | data_crypt |
+------+------------------+
| 1 | ?z#?uػb?7?G[g,< |
+------+------------------+
1 row in set (0,00 sec)
mysql> SELECT i, AES_DECRYPT(b,'crypt_key')...
Las opciones para reforzar la seguridad
1. skip-networking
En el caso de arquitecturas en las que el cliente se encuentra en el mismo equipo que el servidor, puede ser interesante prohibir las conexiones remotas. No solo prevenimos la latencia y posibles problemas relacionados con la red, sino que es a su vez un medio para limitar los riesgos de ataques remotos. La opción skip-networking permite al servidor MySQL no escuchar las conexiones TCP/IP. Las conexiones al servidor MySQL solo podrán efectuarse en local, con los sockets UNIX. En un entorno MS Windows, el principio es el mismo, pero con los protocolos named pipes o shared memory.
En el archivo de configuración my.cnf (o my.INI), activamos skip-networking:
[mysqld]
skip-networking
Ahora es imposible conectar al servidor MySQL utilizando el protocolo TCP/IP.
$ mysql --host=localhost --protocol=tcp
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (111)
Solo queda el protocolo UNIX socket (named pipe o shared memory en Windows):
$ mysql --host=localhost --protocol=socket
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.1.35-log MySQL Community Server (GPL)
Type 'help;' or '\h' for help. Type '\c' to clear the current input
statement.
Mysql>
2. bind-address
La opción bind-address permite asociar (bind) una dirección IP al servidor MySQL; en concreto, a sus interfaces de red. En otras palabras, las conexiones de cliente solo podrán pasar por esta dirección IP para alcanzar el servidor MySQL.
Por ejemplo, para impedir el acceso...
Gestión de usuarios y contraseñas
La gestión de los usuarios de MySQL se realiza por completo a través de tablas específicas que pertenecen al esquema de sistema mysql: user, db, tables_priv, columns_priv, procs_priv.
La tabla user contiene la lista de cuentas de usuarios. Se describen con, entre otras, las columnas host (el nombre de host) y user (el nombre). Estas dos columnas representan la clave primaria de la tabla. También encontraremos la columna password (la contraseña de la cuenta), que se almacena recortada (gracias a la función hash MySQL password()), así como los derechos globales del usuario, como el derecho de hacer inserciones (INSERT), lecturas (SELECT)...
La tabla db contiene los derechos específicos a la base de datos (o esquemas) de cada usuario.
La tabla tables_priv contiene los derechos específicos a una tabla o a una vista.
La tabla columns_priv contiene los derechos específicos a una columna.
La tabla procs_priv contiene los derechos para las rutinas almacenadas, es decir, los procedimientos y funciones almacenados.
1. Conexión a cuentas de usuario
Al arrancar el servidor, las tablas de sistema se cargan en memoria. La tabla user ve entonces sus datos clasificados en función de la columna host, del más específico (localhost, dirección IP) al menos específico (%). Para dos valores de host idénticos, se efectuará una selección adicional sobre la columna user, siempre del más específico (un nombre de cuenta de usuario) al menos específico, es decir, la cuenta del usuario anónimo (’’). Cuando el cliente se conecta, la cuenta de usuario elegida es la primera que corresponde al host (host) de la tabla user ordenada y luego al usuario (user) con la contraseña correcta (password).
El servidor tiene dos usuarios, ’daz’@’%’ y ’daz’@’localhost’.
mysql_root> SELECT user, host FROM mysql.user WHERE user ='daz';
+------+-----------+
| user | host |
+------+-----------+
| daz | % |
| daz | localhost |
+------+-----------+
2 rows in set (0,00 sec)
Conectándose con el usuario daz desde el cliente local (localhost), la conexión se realiza...
Securización de las vistas y rutinas almacenadas
Como hemos visto en la sección sobre derechos, el acceso a los objetos de la base de datos está protegido a nivel de cuentas de usuario por un sistema que nos puede autorizar o no. Sin embargo, aunque tengamos derechos para acceder al objeto (vistas, procedimientos y funciones almacenadas), no es seguro que tengamos el derecho para acceder a los datos a los que se refiere. Para ejecutar una vista (o una rutina), es necesario que el usuario tenga derecho a manipular todos los objetos a los que accede la vista (o la rutina), siempre que la vista (o la rutina) se ejecute a través de un usuario que tenga los derechos adecuados (casi como si usáramos el comando de Linux su).
Para una vista, es la cláusula SQL SECURITY la que permite configurar este comportamiento con los valores:
-
INVOKER: la vista se ejecuta con los derechos del usuario.
-
DEFINER: la vista se ejecuta con los derechos de su creador.
mysql_root> CREATE SQL SECURITY INVOKER VIEW City_ESP1 AS SELECT name
FROM world.City WHERE countrycode='ESP';
mysql_root> CREATE SQL SECURITY DEFINER VIEW City_ESP2 AS SELECT name
FROM world.City WHERE countrycode='ESP';
mysql_user_test> SELECT * FROM City_ESP1 LIMIT 1;
ERROR 1356 (HY000): View 'test.City_ESP1' references invalid table(s)
or column(s) or function(s)...