Inyección SQL
Inyección SQL
La inyección SQL es una técnica de inyección de código que podría destruir su base de datos.
La inyección SQL es una de las técnicas de piratería web más comunes.
La inyección SQL es la colocación de código malicioso en declaraciones SQL, a través de la entrada de una página web.
SQL en páginas web
La inyección de SQL generalmente ocurre cuando le pide a un usuario que ingrese, como su nombre de usuario/ID de usuario, y en lugar de un nombre/ID, el usuario le da una instrucción SQL que, sin saberlo , ejecutará en su base de datos.
Mire el siguiente ejemplo que crea una
SELECT
declaración agregando una variable (txtUserId) a una cadena de selección. La variable se obtiene de la entrada del usuario (getRequestString):
Ejemplo
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
El resto de este capítulo describe los peligros potenciales de utilizar la entrada del usuario en sentencias SQL.
La inyección SQL basada en 1 = 1 es siempre verdadera
Mira el ejemplo anterior de nuevo. El propósito original del código era crear una instrucción SQL para seleccionar un usuario, con una identificación de usuario determinada.
Si no hay nada que impida que un usuario ingrese una entrada "incorrecta", el usuario puede ingresar alguna entrada "inteligente" como esta:
ID de usuario:
Entonces, la declaración SQL se verá así:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
El SQL anterior es válido y devolverá TODAS las filas de la tabla "Usuarios", ya que OR 1=1 siempre es VERDADERO.
¿El ejemplo anterior parece peligroso? ¿Qué sucede si la tabla "Usuarios" contiene nombres y contraseñas?
La declaración SQL anterior es muy similar a esto:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1;
Un hacker podría obtener acceso a todos los nombres de usuario y contraseñas en una base de datos simplemente insertando 105 O 1=1 en el campo de entrada.
La inyección SQL basada en ""="" es siempre verdadera
Aquí hay un ejemplo de un inicio de sesión de usuario en un sitio web:
Nombre de usuario:
Contraseña:
Ejemplo
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass +
'"'
Resultado
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
Un hacker podría obtener acceso a nombres de usuario y contraseñas en una base de datos simplemente insertando " O ""=" en el cuadro de texto de nombre de usuario o contraseña:
Nombre de usuario:
Contraseña:
El código en el servidor creará una instrucción SQL válida como esta:
Resultado
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
El SQL anterior es válido y devolverá todas las filas de la tabla "Usuarios", ya que OR ""="" siempre es VERDADERO.
Inyección SQL basada en sentencias SQL por lotes
La mayoría de las bases de datos admiten sentencias SQL por lotes.
Un lote de sentencias SQL es un grupo de dos o más sentencias SQL, separadas por punto y coma.
La declaración SQL a continuación devolverá todas las filas de la tabla "Usuarios", luego eliminará la tabla "Proveedores".
Ejemplo
SELECT * FROM Users; DROP TABLE Suppliers
Mira el siguiente ejemplo:
Ejemplo
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Y la siguiente entrada:
Identificación de usuario:
La instrucción SQL válida se vería así:
Resultado
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers;
Usar parámetros de SQL para la protección
Para proteger un sitio web de la inyección SQL, puede usar parámetros SQL.
Los parámetros SQL son valores que se agregan a una consulta SQL en el momento de la ejecución, de manera controlada.
Ejemplo de ASP.NET Razor
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Tenga en cuenta que los parámetros se representan en la instrucción SQL mediante un marcador @.
El motor SQL verifica cada parámetro para asegurarse de que sea correcto para su columna y se trate literalmente, y no como parte del SQL que se ejecutará.
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);
Ejemplos
Los siguientes ejemplos muestran cómo crear consultas parametrizadas en algunos lenguajes web comunes.
SELECCIONE DECLARACIÓN EN ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();
INSERTAR EN LA DECLARACIÓN 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();
INSERTAR EN LA DECLARACIÓN 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();