MySQL - e inyección SQL
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 abierto a un problema de seguridad conocido como SQL Injection. Este capítulo le enseñará cómo ayudar a evitar que esto suceda y le ayudará a proteger sus scripts y declaraciones MySQL.
La inyección de SQL generalmente ocurre cuando le pides a un usuario una entrada, como su nombre y en lugar de un nombre, te dan una declaración de MySQL que, sin saberlo, ejecutarás en tu 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['username'], $matches)) {
$result = mysql_query("SELECT * FROM users WHERE username = $matches[0]");
} else {
echo "username not accepted";
}
Para demostrar este problema, considere el siguiente extracto.
// supposed input
$name = "Qadir'; DELETE FROM users;";
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, $ name solo contendría caracteres alfanuméricos y quizás espacios. Pero aquí, agregando una consulta completamente nueva a$name, 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, el mysql_query()La función no permite apilar consultas o ejecutar 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, realiza felizmente consultas apiladas, ejecutando todas las consultas proporcionadas en una cadena y creando un problema de seguridad serio.
Prevención de la inyección de SQL
Puede manejar todos los caracteres de escape de forma inteligente en lenguajes de script como PERL y PHP. La extensión MySQL para PHP proporciona la funciónmysql_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 LIKE
Para abordar el dilema de LIKE, un mecanismo de escape personalizado debe convertir los caracteres% y _ proporcionados por el usuario en literales. Utilizaraddcslashes(), una función que le permite especificar un rango de caracteres para escapar.
$sub = addcslashes(mysql_real_escape_string("%something_"), "%_");
// $sub == \%something\_
mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");