Una Inyección SQL puede destruir su base de datos.
SQL en páginas Web
En los capítulos anteriores, que han aprendido a recuperar datos de bases de datos (y actualización), el uso de SQL.
Cuando SQL se utiliza para mostrar datos en una página web, es común para que los usuarios de Internet de entrada de sus propios valores de búsqueda.
Como las sentencias SQL son de sólo texto, es fácil, con un pequeño pedazo de código de computadora, para cambiar dinámicamente las sentencias SQL para proporcionar al usuario con los datos seleccionados:
servidor de códigos
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
El ejemplo anterior, crea una instrucción de selección mediante la adición de una variable (txtUserId) a una cadena de selección. La variable se obtiene de la entrada del usuario (Request) a la página.
El resto de este capítulo se describen los peligros potenciales de la utilización de la entrada del usuario en las instrucciones SQL.
Inyección SQL
la inyección de SQL es una técnica en la que los usuarios maliciosos pueden inyectar comandos SQL en una sentencia de SQL, a través de entrada página web.
comandos SQL inyectados pueden alterar instrucción SQL y poner en peligro la seguridad de una aplicación web.
Inyección SQL Basado en 1 = 1 siempre es cierto
Mira el ejemplo anterior, una vez más.
Digamos que el propósito original del código era crear una instrucción SQL para seleccionar un usuario con un identificador de usuario dado.
Si no hay nada para evitar que un usuario la entrada al "wrong" de entrada, el usuario puede introducir algún "smart" de entrada de la siguiente manera:
Identidad de usuario:
Resultado del servidor
SELECT * FROM Users WHERE UserId = 105 or 1=1
El SQL anterior es válido. Se devolverá todas las filas de la tabla de usuarios, ya que 1 = 1 es siempre cierto.
¿El ejemplo anterior parece peligroso? ¿Qué pasa si la tabla de usuarios contiene los nombres y contraseñas?
La sentencia SQL anterior es mucho lo mismo que esto:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1
Un hacker inteligente podría obtener acceso a todos los nombres de usuario y contraseñas en una base de datos con sólo insertar 105 o 1 = 1 en la casilla correspondiente.
Inyección SQL Sobre la base de ""="" siempre es cierto
Aquí es una construcción común, que se utiliza para verificar la conexión del usuario a un sitio web:
Nombre de usuario:
Contraseña:
servidor de códigos
uName = getRequestString("UserName");
uPass = getRequestString("UserPass");
sql = "SELECT * FROM Users WHERE Name ='" + uName + "' AND Pass ='" + uPass + "'"
Un hacker inteligente podría obtener acceso a los nombres de usuario y contraseñas en una base de datos con sólo insertar "o ""=" en el cuadro de texto nombre de usuario o contraseña.
El código en el servidor creará una instrucción SQL válida la siguiente manera:
Resultado
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
El resultado es válido SQL. Se devolverá todas las filas de la tabla de usuarios, desde donde "" = "" es siempre cierto.
La inyección SQL Con base en instrucciones SQL por lotes
La mayoría de las bases de datos compatibles con SQL por lotes, separados por punto y coma.
Ejemplo
SELECT * FROM Users; DROP TABLE Suppliers
El SQL anterior devolverá todas las filas en la tabla de usuarios y, a continuación, elimine la tabla llamados Proveedores.
Si tuviéramos el siguiente código de servidor:
servidor de códigos
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Y la siguiente entrada:
Identidad de usuario:
El código en el servidor crearía una instrucción SQL válida la siguiente manera:
Resultado
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers
Parámetros para la Protección
Algunos desarrolladores web utilizan una "blacklist" de las palabras o caracteres que desea buscar en la entrada de SQL, para evitar ataques de inyección SQL.
Esta no es una idea muy buena. Muchas de estas palabras (como eliminar o gota) y caracteres (como puntos y comas y comillas), se utilizan en el lenguaje común, y debe ser permitido en muchos tipos de entrada.
(En realidad debería ser perfectamente legal para introducir una instrucción SQL en un campo de base de datos.)
La única manera probada para proteger un sitio web desde los ataques de inyección SQL, es utilizar los parámetros de SQL.
los parámetros de SQL son valores que se agregan a una consulta SQL en tiempo de ejecución, de una manera controlada.
Ejemplo ASP.NET Razor
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Tenga en cuenta que los parámetros están representados en la instrucción SQL por un marcador @.
El motor de SQL comprueba cada parámetro para asegurarse de que es correcta para su columna y son tratados literalmente, y no como parte del SQL para su ejecución.
Otro ejemplo
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City)
Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);
Usted acaba de aprender a evitar la inyección de SQL. Una de las principales vulnerabilidades de sitios web.
Ejemplos
Los siguientes ejemplos muestran cómo construir consultas con parámetros en algunos lenguajes web comunes.
Instrucción SELECT de ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserID);
command.ExecuteReader();
INSERT INTO en ASP.NET:
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City)
Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();
INSERT INTO en PHP:
$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();