Cualquiera que utilice MySQL en un ordenador conectado a Internet debería leer esta sección para evitar los errores de seguridad más comunes.
Al tratar el tema de la seguridad, hacemos hincapié en la necesidad de proteger totalmente la máquina completa (no únicamente el servidor MySQL) contra todos los tipos de ataques posibles; intercepción pasiva de paquetes, alteración, reproducción de comandos (playback), y denegación de servicio. Aquí no tratamos todos los aspectos de disponibilidad y tolerancia a fallos.
Para todas las conexiones, consultas, y otras operaciones que los usuarios pueden intentar realizar, MySQL utiliza seguridad basada en Listas de Control de Acceso (ACLs). También hay algún soporte para conexiones cifradas mediante SSL entre clientes y servidores MySQL. Muchos de los conceptos que aquí se exponen no son específicos de MySQL; las mismas ideas generales se pueden aplicar a cualquier aplicación.
Al ejecutar MySQL, siga siempre que sea posible estas recomendaciones:
¡No de nunca a nadie (excepto a la
cuenta root
de MySQL acceso a la tabla
user
en la base de datos
mysql
! Esto es crítico.
La clave cifrada es la verdadera clave
en MySQL. Cualquiera que sepa cual es la clave
que hay en la tabla user
y tenga acceso a
la máquina host de la cuenta registrada
puede acceder fácilmente como ese
usuario.
Estudie el sistema de privilegios de acceso de MySQL. Las
sentencias GRANT
y
REVOKE
se utilizan para controlar el
acceso a MySQL. No otorgue más privilegios de los
necesarios. Nunca otorgue privilegios a un mismo usuario sin
tener en cuenta el equipo desde el que se conecta.
Lista de comprobaciones:
Pruebe el comando mysql -u root
. Si
es capaz de conectar al servidor sin la necesidad de
introducir una clave, tiene problemas. ¡Cualquiera
puede conectar a su servidor MySQL como el usuario
root
de MySQL con privilegios
totales! Revise las instrucciones de instalación de
MySQL, prestando atención en concreto a la información
sobre establecer una clave para el usuario
root
. Consulte
Sección 2.9.3, “Hacer seguras las cuentas iniciales de MySQL”.
Utilice la sentencia SHOW GRANTS
y
compruebe quién tiene acceso a qué. Después utilice
la sentencia REVOKE
para denegar los
privilegios que no son necesarios.
No almacene ninguna clave sin cifrar en su base de datos. Si
alguien tuviera acceso a su ordenador, el intruso podría
obtener la lista completa de claves y utilizarlas. En vez de
eso, utilice MD5()
,
SHA1()
, o cualquier otra función de
hashing de un sentido.
No elija claves que puedan aparecer en un diccionario. Existen programas especiales para romperlas. Incluso claves como ``xperro98'' son muy malas. Es mucho mejor ``oweei98'', que contiene la misma palabra ``perro'' pero escrita desplazándose una tecla a la izquierda en un teclado QWERTY convencional. Otro método es usar ``Mtupc'', que ha sido tomada de las primeras letras de cada palabra de la frase ``María tuvo un pequeño corderito.'' Así es fácil de recordar y escribir, pero difícil de adivinar para cualquiera que no la conozca.
Invierta en un firewall. Le protegerá de al menos el 50% de todos los tipos de vulnerabilidades de cualquier software. Ponga MySQL tras el firewall o en una zona desmilitarizada (DMZ).
Lista de comprobaciones:
Intente escanear sus puertos desde Internet utilizando
una herramienta como nmap
. MySQL
utiliza el puerto 3306 por defecto. Este puerto no
debería ser accesible desde lugares no confiables. Otra
manera simple de probar si el puerte MySQL está abierto
o no es intentar el siguiente comando desde alguna
máquina remota, donde server_host
es
la máquina en la que su servidor MySQL se está
ejecutando:
shell> telnet server_host 3306
Si consigue conectar y algunos caracteres extraños, el
puerto está abierto, y debería cerrarlo en su firewall
o router, a menos que tenga una buena razón para
mantenerlo abierto. Si el comando
telnet
no consigue conectar o la
conexión es rechazada, entonces el puerto se encuentra
bloqueado, que es como queremos que esté.
No confíe en ningún dato enviado por los usuarios de sus
aplicaciones. Pueden intentar engañar a su código
introduciendo secuencias de caracteres especiales en
formularios webs, URLs, o cualquier aplicación que haya
desarrollado. Asegúrese de que su aplicación permance
segura si un usuario introduce algo como ``; DROP
DATABASE mysql;
''. Este es un ejemplo algo
extremo, pero los mayores agujeros de seguridad y pérdidas
de datos pueden ocurrir como resultado de hackers utilizando
técnicas similares, si no se está preparado para ellas.
Un error común es proteger únicamente valores de tipo
cadena de caracteres. Recuerde comprobar los datos
numéricos también. Si una aplicación genera una consulta
como SELECT * FROM table WHERE ID=234
cuando un usuario introduce el valor 234
,
el usuario podría introducir el valor 234 OR
1=1
para provocar que la aplicación genere la
consulta SELECT * FROM table WHERE ID=234 OR
1=1
. Como resultado, el servidor extraerá todos
los registros en la tabla. Esto, además de exponer cada
registro, causa una carga excesiva en el servidor. La manera
más simple de protegerse frente a este tipo de ataque es
utilizar comillas simples alrededor de las constantes
numéricas: SELECT * FROM table WHERE
ID='234'
. Si el usuario entrase información
extra, todo sería parte de la cadena de caracteres. En un
contexto numérico, MySQL automáticamente convierte esta
cadena en un número, y elimina cualquier carácter no
númerico del final que la cadena pueda contener.
A veces la gente piensa que si una base de datos contiene sólo datos de dominio público, no tiene por qué ser protegida. Esto es incorrecto. Aunque sea admitible mostrar cualquier registro de la base de datos, siempre se debería proteger contra ataques de tipo denegación de servicio (por ejemplo, aquellos que se basan en la técnica del párrafo precedente, que causan que el servidor malgaste recursos). Si no, el servidor podría quedar inservible para sus usuarios legítimos.
Lista de comprobaciones:
Intente introducir comillas simples y dobles
(''
' y '"
') en
todos sus formularios web. Si obtiene cualquier clase de
error MySQL, investigue el problema sin demora.
Intente modificar las URLs dinámicas añadiendo las
cadenas %22
('"
'),
%23
('#
'), y
%27
(''
').
Intente modificar los tipos de datos en las URLs dinámicas de tipos numéricos a alfanuméricos, usando los caracteres mostrados en los ejemplos previos. Su aplicaicón debería ser segura contra estos y otros ataques similares.
Intente introducir letras, espacios, y símbolos especiales en vez de números en los campos numeicos. Su aplicación debería eliminarlos antes de pasarlos a MySQL, o en todo caso generar un error. ¡Pasar valores sin comprobar a MySQL es muy peligroso!
Compruebe el tamaño de los datos antes de pasárselos a MySQL.
Haga que su aplicación se conecte a la base de datos utilizando un nombre de usuario diferente del que utiliza para tareas administrativas. No dé a sus aplicaciones ningún acceso que no necesiten.
Muchas interfaces de programación de aplicaciones proveen alguna manera de preceder con caracteres de escape los caracteres especiales en sus datos. Usados adecuadamente, esto previene que los usuarios de las aplicaciones introduzcan valores que provoquen que la aplicación genere sentencias con efectos diferentes a los que usted pretendía:
API MySQL de C: Utilice la función
mysql_real_escape_string()
.
MySQL++: Utilice los modificadores
escape
y quote
para streams
PHP: Utilice la función
mysql_escape_string()
, que está
basada en la función del mismo nombre de la API MySQL
de C. (Con versiones anteriores a PHP 4.0.3, utilice
addslashes()
en cambio.) En PHP 5,
puede utilizar la extensión mysqli
,
que soporta los protocolo de autentificación y clave de
acceso mejorados de MySQL, así como las sentencias
preparadas con placeholders.
DBI de Perl: Utilice el método
quote()
o utilice placeholders.
JDBC de Java: Utilice un objeto
PreparedStatement
y placeholders.
Otras interfaces de programación deberían tener capacidades similares.
No transmita datos sin cifrar por Internet. Esta información es accesible para cualquiera que tenga el tiempo y la habilidad para interceptarla y utilizarla para sus propios propósitos. En vez de eso, utilice un protocolo de cifrado como SSL o SSH. MySQL soporta conexiones SSL internas desde la versión 4.0.0. El redireccionamiento de puertos de SSH se puede utilizar para crear un tunel cifrado (y comprimido) para la comunicación.
Aprenda a utilizar las herramientas
tcpdump
y strings
. En
la mayoría de los casos, usted puede comprobar si los
flujos de datos de MySQL están cifrados ejecutando un
comando como el siguiente:
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
(Esto funciona en Linux, y debería funcionar, con pequeñas modificaciones en otros sistemas.) Atención: Si no ve los datos en formato de texto, esto no siempre quiere decir que la información esté realmente cifrada. Si necesita un alto nivel de seguridad, debería consultar a un experto en la materia.
Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.