09 agosto 2010

Fortificación de MySQL - 1/3

Parte 1 de 3
Parte 2 de 3
Parte 3 de 3
 
MySQL se ha convertido en el motor de bases de datos más usado y potente del mundo opensource. Pero debido a la versatilidad que ofrece,  la configuración por defecto en los paquetes de distribución y el suyo propio no considera todos los aspectos de seguridad que se han de contemplar en un entorno controlado.

Las siguientes entradas pretenden enumerar brevemente cuales son los puntos más importantes que se deberían revisar en una implantación segura de esta aplicación.

El archivo de configuración de MySQL se encuentra en el archivo: "C:\Program Files\MySQL\MySQL Server 5.x" en el caso de Windows o /etc/mysql/my.cnf en el caso de sistemas Linux.

1.- Restringir o deshabilitar el acceso mediante red: si el servicio se encuentra en el mismo equipo que la aplicación que realiza las consultas no es necesario que mysql escuche peticiones en todos los interfaces de red. Una de las medidas más importantes es dejar únicamente el puerto abierto en aquellas IPs donde sea estrictamente necesario. Para efectuar este cambio y que solo se pueda conectar localmente, en la sección [mysqld] indicar:
[mysqld]
bind-address=127.0.0.1
Si por el contrario queremos deshabilitar por completo el acceso mediante un socket de red, basta con añadir la directiva skip-network:
[mysqld]
skip-networking

Por último, si se ha de utilizar el servicio en remoto, todos los usuarios de las aplicaciones que conecten deben estar limitados mediante su dirección de origen (host). Desde el prompt de mysql:
mysql> GRANT SELECT, INSERT ON basededatos.* TO 'usuario'@'host';

2.- Eliminar el acceso a la tabla "user" de la base de datos a todos los usuarios excepto los de administración: de esta forma otros usuarios del motor no podrán consultar las contraseñas y accesos que contiene MySQL.

Para ver los privilegios de un usuario:
mysql> SHOW GRANTS FOR 'usuario'@'host';
Para eliminar privilegios:
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM usuario;

3.- Deshabilitar el uso de LOCAL INFILE: mediante estos permisos se pueden leer ficheros del sistema operativo desde la base de datos, algo común cuando se explota una inyección de código SQL. Para deshabilitar esta función se configura la variable local-infile a 0:

En MySQL  anterior a 5.5
[mysqld]
set-variable=local-infile=0

Para MySQL 5.1 o superior:
[mysqld]
local-infile=0

4.- Cambio de nombre de usuario root y su contraseña: al igual que en los sistemas operativos, se recomienda que el administrador de la base de datos no sea el usuario root y mantenga una contraseña segura. Si MySQL es una versión superior a 5.0.2
mysql> RENAME USER root TO r00tz

En caso de que la versión de MySQL sea inferior:
mysql> use mysql;
mysql> update user set user="nuevousuario" where user="root";
mysql> flush privileges;

Para modificar la contraseña de un usuario se puede utilizar el comando mysqladmin o se puede hacer mediante SQL:
mysql> use mysql;
mysql> SET PASSWORD FOR 'username'@'%hostname' = PASSWORD('newpass');
5.- Eliminar la base de datos "test": que se distribuye con el servicio y no es necesaria. Para hacerlo directamente en SQL:
mysql> drop database test;
O mediante línea de comandos:
shell> mysqladmin -u username -p drop test 

6.- Eliminación de cuentas obsoletas y acceso anónimo: que son creadas en algunas instalaciones de MySQL, para comprobar si existen este tipo de usuarios:
mysql> select * from mysql.user where user="";
Si se muestran usuarios, se pueden eliminar mediante DROP USER (en MySQL 5)
mysql> DROP USER "";

Si la versión de MySQL es inferior a 5.0:
mysql> use mysql;
mysql> DELETE FROM user WHERE user="";
mysql> flush privileges;


Referencias:

13 comments :

rooot dijo...

Muy buen trabajo!! Y me ha venido de perlas :D
Muchas gracias

Broda Noel dijo...

Genial el trabajo.
Podria colocarlo en http://www.tecnovoid.com ?

fossie dijo...

Buen trabajo, aun hay muchos portales web que no tienen ni la seguridad minima y su MySQL esta demasiado expuesto.

Por cierto, ¿cuando se escribió esta entrada? lo digo porque tengo este blog en mi lista de blogs y ayer ya me aparecia el título de esta entrada pero no se podia acceder al contenido y hoy veo que se ha vuelto a actualizar y ya esta disponible.

Anónimo dijo...

Hay un pequeño problema con el método para cambiar la contraseña de root (o cualquier otro usuario): en UNIX, el cliente de línea de comandos de MySQL almacena el historial de los comandos tecleados (que en este caso contendrá la contraseña asignada), así que, si vas a cambiar la contraseña usando SET PASSWORD, acuérdate de evitar grabar el historial de comandos.

Directamente de la página de manual de mysql:

On Unix, the mysql client writes a record of executed statements to a history file. By default, the history file is named mysql_history and is created in your home directory. To specify a different file, set the value of the MYSQL_HISTFILE environment variable.

If you do not want to maintain a history file, first remove .mysql_history if it exists, and then use either of the following techniques:

* Set the MYSQL_HISTFILE variable to /dev/null. To cause this setting to take effect each time you log in, put the setting in one of your shell's startup files.

* Create .mysql_history as a symbolic link to /dev/null:
shell> ln -s /dev/null $HOME/.mysql_history

You need do this only once.

Alejandro Ramos dijo...

@fossie, efectivamente tuvimos un problemilla con la hora de la publicación, siento las molestias :)

@anónimo, quedan 2 entradas, borrar el historial viene en la siguiente... y bastantes cosas más!

Anónimo dijo...

@Alejandro

Por supuesto, pero puede que tus lectores sólo lean la primera (parece que "rooot" ya ha empezado a ello), así que me pareció bien comentarlo.

No comenté tampoco la opción de cambiar el algoritmo de cifrado, que es recomendable para versiones anteriores a la 5.1 (si recuerdo bien, a partir de esta versión el algoritmo por defecto no es débil), porque pensé que ya lo incluirías en la siguiente, aunque a lo mejor convendría cubrir todo aquello relacionado con las contraseñas en un mismo post, para evitar que alguien "se quede a la mitad".

Alejandro Ramos dijo...

@Anónimo: si solo leen la primera, merecen que les hackeen ;)

Jordi Prats dijo...

el uso de set-variable era para versiones anteriores a la 4, por lo que ya no se usa y se quitará en la versión 5.5:

http://dev.mysql.com/doc/refman/5.1/en/program-variables.html

Yo dejaría de usar esta sintaxi

Alejandro Ramos dijo...

¡Gracias Jordi!, actualizo la entrada

Zerial dijo...

Solo un comentario;

No en todos los "Linux" se encuentra en /etc/mysql/my.cnf". Depende de la distribución y si se compila manualmente dependerá de los parametros con los que se configure y compile. Hay distribuciones que lo dejan en /etc/my.cnf


El resto del articulo muy bueno!

Alejandro Ramos dijo...

@Zerial: muchas gracias. Tampoco en todos los windows la carpeta es "C:\Program Files", depende del idioma del sistema operativo. Aunque cuando escribí la entrada pensaba que esas cosas ya se sobreentendian :)

Un saludo.

Alejandro Ramos dijo...

¡Gracias Jordi!, actualizo la entrada

Alejandro Ramos dijo...

@Zerial: muchas gracias. Tampoco en todos los windows la carpeta es "C:\Program Files", depende del idioma del sistema operativo. Aunque cuando escribí la entrada pensaba que esas cosas ya se sobreentendian :)

Un saludo.