3.1 KiB
title | localeTitle |
---|---|
Query Parameterization | Parametrización de consultas |
Parametrización de consultas
Un error común cuando se conecta su programa a una base de datos es aceptar la entrada de un usuario y aplicarla directamente a la base de datos sin verificarla primero. Este es un hábito peligroso, y es posible que escuche a desarrolladores más experimentados que advierten a otros que "desinfecten las entradas" o "parametricen consultas".
Comencemos con un breve ejemplo que demuestra el problema:
(los siguientes fragmentos están escritos en C # para MySQL, pero el concepto se aplica a cualquier idioma y base de datos)
El problema
public void RetrieveEmployeeInfo(string username)
{
using (var connection = new MySqlConnection("valid_connection_string"))
{
var query = "SELECT * FROM EMPLOYEES WHERE USERNAME = '" + username + "'";
using (var command = new MySqlCommand(query, connection))
{
var reader = command.ExecuteReader();
while (reader.Read())
{
// do something with the results of your query, like display the employee
}
}
}
}
A primera vista, eso puede parecer bastante inofensivo. Si el usuario escribe "JDOE" en su programa y pasa a esta función, terminará ejecutando una consulta como esta:
SELECT * FROM EMPLOYEES WHERE USERNAME = 'JDOE';
El problema se vuelve más evidente cuando considera lo que sucede si el usuario no escribe lo que espera. ¿Qué pasa si JDOE'; DROP TABLE EMPLOYEES; --
algo como JDOE'; DROP TABLE EMPLOYEES; --
? Su cadena de "consulta" ahora tiene este aspecto, que seleccionará la información del empleado, luego eliminará toda la tabla de EMPLEADOS.
SELECT * FROM EMPLOYEES WHERE USERNAME = 'JDOE'; DROP TABLE EMPLOYEES; --'
La solución
Para evitar problemas como este, podemos parametrizar nuestras consultas. Veamos otro ejemplo:
public void RetrieveEmployeeInfo(string username)
{
using (var connection = new MySqlConnection("valid_connection_string"))
{
var query = "SELECT * FROM EMPLOYEES WHERE USERNAME = @username";
using (var command = new MySqlCommand(query, connection))
{
command.Parameters.AddWithValue("username", username);
var reader = command.ExecuteReader();
while (reader.Read())
{
// do something with the results of your query, like display the employee
}
}
}
}
Ahora que pasa si el usuario escribe JDOE'; DROP TABLE EMPLOYEES; --
? Nuestro programa termina ejecutando una consulta como esta y, al no encontrar ningún empleado cuyo nombre de usuario realmente coincida con esa entrada, simplemente no devuelve ningún registro.
SELECT * FROM EMPLOYEES WHERE USERNAME = 'JDOE\'; DROP TABLE EMPLOYEES; --'
Independientemente del idioma o la base de datos que esté utilizando, si considera consultar la base de datos utilizando los comentarios del usuario, consulte la documentación para conocer la forma correcta de parametrizar las consultas.