Inyección SQL

Si toma la entrada de un usuario a través de una página web y la inserta en una base de datos SQL, 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 sentencias SQL en los scripts del lado del servidor, como un script PERL.

La inyección generalmente ocurre cuando le pide a un usuario una entrada, como su nombre y en lugar de un nombre, le dan una declaración SQL que, sin saberlo, ejecutará en su base de datos. Nunca confíe en los datos proporcionados por el usuario, procese estos datos solo después de la validación; como regla, esto se hacePattern Matching.

En el siguiente ejemplo, el name está restringido a los caracteres alfanuméricos más el subrayado y a 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 CUSTOMERS 
      WHERE name = $matches[0]");
} else {
   echo "user name not accepted";
}

Para demostrar el problema, considere este extracto:

// supposed input
$name = "Qadir'; DELETE FROM CUSTOMERS;";
mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");

Se supone que la llamada a la función recupera un registro de la tabla CUSTOMERS donde la columna de nombre coincide con el nombre especificado por el usuario. Bajo circunstancias normales,$namesolo contendría caracteres alfanuméricos y quizás espacios, como la cadena ilia. Pero aquí, al agregar 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 la tabla CUSTOMERS.

Afortunadamente, si usa MySQL, el mysql_query()La función no permite apilar consultas o ejecutar múltiples consultas SQL 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 felizmente realice 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 CUSTOMERS 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("%str"), "%_");
// $sub == \%str\_
mysql_query("SELECT * FROM messages 
   WHERE subject LIKE '{$sub}%'");