77 lines
3.1 KiB
Markdown
77 lines
3.1 KiB
Markdown
|
---
|
||
|
title: Query Parameterization
|
||
|
localeTitle: 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
|
||
|
|
||
|
```csharp
|
||
|
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:
|
||
|
|
||
|
```sql
|
||
|
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.
|
||
|
|
||
|
```sql
|
||
|
SELECT * FROM EMPLOYEES WHERE USERNAME = 'JDOE'; DROP TABLE EMPLOYEES; --'
|
||
|
```
|
||
|
|
||
|
### La solución
|
||
|
|
||
|
Para evitar problemas como este, podemos parametrizar nuestras consultas. Veamos otro ejemplo:
|
||
|
|
||
|
```csharp
|
||
|
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.
|
||
|
|
||
|
```sql
|
||
|
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.
|