Si toma la entrada del usuario a través de una página web y la inserta en una base de datos MySQL, existe la posibilidad de que se haya quedado completamente abierto ante un problema de seguridad conocido como Inyección de SQL. Este capítulo le enseñará cómo evitar que esto suceda y lo ayudará a proteger sus scripts y declaraciones MySQL.
La inyección SQL generalmente ocurre cuando le pide a un usuario una entrada, como su nombre y en lugar de un nombre, le dan una declaración de MySQL que, sin saberlo, ejecutará en su base de datos.
Nunca confíe en los datos proporcionados por un usuario, procese estos datos solo después de la validación; como regla, esto se hace mediante la coincidencia de patrones. En el siguiente ejemplo, el nombre de usuario está restringido a caracteres alfanuméricos más un guión bajo y una longitud de entre 8 y 20 caracteres; modifique estas reglas según sea necesario.
if (preg_match ("/ ^ \ w {8,20} $ /", $ _GET ['nombre de usuario'], $ coincidencias)) {
$ result = mysql_query ("SELECT * FROM users WHERE username = $ coincide con [0]");
} else {
echo "nombre de usuario no aceptado";
}
Para demostrar este problema, considere el siguiente extracto.
// supuesta entrada
$ name = "Qadir '; BORRAR DE los usuarios;";
mysql_query ("SELECT * FROM users WHERE name = '{$ name}'");
Se supone que la llamada a la función recupera un registro de la tabla de usuarios, donde la columna de nombre coincide con el nombre especificado por el usuario. En circunstancias normales, $ nombre solo contendría caracteres alfanuméricos y quizás espacios. Pero aquí, al agregar una consulta completamente nueva a $ nombre, la llamada a la base de datos se convierte en un desastre. La consulta DELETE inyectada elimina todos los registros de los usuarios.
Afortunadamente, si usa MySQL, la función mysql_query () no permite el apilamiento de consultas o la ejecución de múltiples consultas en una sola llamada de función. Si intenta apilar consultas, la llamada falla.
Sin embargo, otras extensiones de base de datos PHP, como SQLite y PostgreSQL, realizan consultas apiladas, ejecutan todas las consultas proporcionadas en una cadena y crean un grave problema de seguridad.
Prevención de la inyección SQL
Puede manejar todos los caracteres de escape con inteligencia en lenguajes de script como PERL y PHP. La extensión MySQL para PHP proporciona la función mysql_real_escape_string () para escapar de los caracteres de entrada que son especiales para MySQL.
if (get_magic_quotes_gpc ()) {
$ name = stripslashes ($ name);
}
$ name = mysql_real_escape_string ($ name);
mysql_query ("SELECT * FROM users WHERE name = '{$ name}'");
El dilema de LIKE
Para abordar el dilema de LIKE, un mecanismo de escape personalizado debe convertir los caracteres% y _ proporcionados por el usuario a literales. Use addcslashes (), una función que le permite especificar un rango de caracteres para escapar.
$ sub = addcslashes (mysql_real_escape_string ("% something_"), "% _");
// $ sub == \% algo \ _
mysql_query ("SELECCIONAR * DE LOS mensajes, DONDE el asunto, COMO" {$ sub}% '"