securizar mysql para tus webs

7 de mayo de 2008

He visto varios servidores donde el administrador utiliza el mismo usuario root del MySql por defecto para dar acceso a diferentes Webs PHP de diferentes clientes/amigos... todo hay que decir que el chaval estaba empezando.

Para definir permisos para las diferentes Webs tenemos que tener claro que cada aplicación Web PHP tendrá su usuario de conexión al MySql, que las conexiones de estos usuarios se realizarán en localhost (porque las paginas Web estan alojadas en el mismo servidor) y por ultimo tenemos que tener claro que instrucciones SQL ejecutan las paginas (lo normal es utilizar solo instrucciones DML).

Si queremos una mínima seguridad para los accesos PHP a MySql tendríamos que hacer esto como mínimo.

1) Borrar todas las bbdd no necesarias. Como por ejemplo la base de datos test que instala MySql por defecto.

mysql> DROP DATABASE test;
2) Añadir un buen password al usuario root (que por defecto no tiene), que root solo pueda conectar en local (localhost) y crear otro usuario admin para poder administrar remotamente solo desde ciertas IP (como la maquina del administrador, el dpt. de informática, etc). Supondremos que la maquina del administrador es la 192.168.1.45.

mysql> GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' identified by 'un_buen_pwd';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'admin'@'192.168.1.45' identified by 'un_buen_pwd';
mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('otro_buen_pwd');
Tambien podemos asignar un password al administrador con la utilidad de MySql "mysqladmin".

# mysqladmin -u root password "otro_buen_psw"
He visto manuales que dicen de eliminar el permiso de root para el conectarse localmente. Yo personalmente no lo haría.

3) Ahora solo nos queda añadir tantos usuarios MySql como paginas Web tengamos alojadas. Si tenemos tres Webs A, B y C haríamos:

mysql> GRANT select, insert, delete, update ON A.* TO 'usuarioA'@'localhost' identified by 'psw_de_A';
mysql> GRANT select, insert, delete, update ON B.* TO 'usuarioB'@'localhost' identified by 'psw_de_B';
mysql> GRANT select, insert, delete, update ON C.* TO 'usuarioC'@'localhost' identified by 'psw_de_C';
mysql> FLUSH PRIVILEGES;
Con estas instrucciones tenemos más que suficientes para una típica aplicación PHP que solo utiliza instrucciones DML en SQL. Si por ejemplo la pagina web A utilizara creación de tablas temporales, pues prodríamos poner:

mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'usuarioA'@'localhost':
mysql> GRANT select, insert, delete, update, create temporary tables ON A.* TO 'usuarioA'@'localhost' identified by 'psw_de_A';
4) Para finalizar podríamos comprobar todos los usuarios existentes y ver que permisos tienen mirando la tabla "user" de la bbdd del mysql.

mysql> USE mysql;
mysql> SELECT * FROM user;
También podemos ver los permisos otorgados con un "SHOW GRANTS".

Aunque estas reglas son sencillas lo mejor es el sentido común. Por ejemplo a la hora de dar permisos no de nunca permisos de GRANT ni REVOKE a usuarios que no sea el administrador. Tampoco de acceso a la tabla user que es donde estan todas las contraseñas (aunque estas esten cifradas).

Y sobre todo leer la guía de seguridad general y la gestión de usuarios.