Pregunta

.NET, Java y otras API de bases de datos de alto nivel en varios lenguajes a menudo proporcionan técnicas conocidas como declaraciones preparadas y enlace de parámetros en lugar de enviar comandos de texto sin formato al servidor de la base de datos.Lo que me gustaría saber es qué sucede cuando ejecutas una declaración como esta:

SqlCommand cmd = new SqlCommand("GetMemberByID");
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter("@ID", memberID);
para.DbType = DbType.Integer;
cmd.Parameters.Add(param);

Sé que esta es una mejor práctica.Los ataques de inyección SQL se minimizan de esta manera.Pero, ¿qué sucede exactamente cuando ejecutas estas declaraciones?¿El resultado final sigue siendo una cadena segura de SQL?Si no, ¿cuál es el resultado final?¿Y esto es suficiente para prevenir ataques de inyección SQL?

¿Fue útil?

Solución

La página del manual de MySQL en declaraciones preparadas proporciona mucha información (que debería aplicarse a cualquier otro RDBMS).

Básicamente, su declaración se analiza y procesa con anticipación, y los parámetros se envían por separado en lugar de manejarse junto con el código SQL.Esto elimina los ataques de inyección de SQL porque el SQL se analiza incluso antes de que se establezcan los parámetros.

Otros consejos

en términos sencillos:Si se envía una declaración preparada, la base de datos usará un plan si está disponible, no es necesario volver a crear un plan cada vez que se envía esta consulta, sino que solo han cambiado los valores de los parámetros.Esto es muy similar a cómo funcionan los procs, el beneficio adicional de los procs es que puedes dar permiso solo a través de los procs y no a las tablas subyacentes en absoluto.

Si está utilizando MS SQL, cargue el generador de perfiles y verá qué declaraciones SQL se generan cuando utiliza consultas parametrizadas.Aquí hay un ejemplo (estoy usando Enterprise Libary 3.1, pero los resultados son los mismos usando SqlParameters directamente) en SQL Server 2005:

string sql = "SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did";
Database db = DatabaseFactory.CreateDatabase();
using(DbCommand cmd = db.GetSqlStringCommand(sql))
{
  db.AddInParameter(cmd, "DomName", DbType.String, "xxxxx.net");
  db.AddInParameter(cmd, "Did", DbType.Int32, 500204);

  DataSet ds = db.ExecuteDataSet(cmd);
}

Esto genera:

exec sp[underscore]executesql N'SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did',
  N'@DomName nvarchar(9),
  @Did int',
  @DomName=N'xxxxx.net',
  @Did=500204

También puede ver aquí que, si se pasaron caracteres de comillas como parámetros, se escapan en consecuencia:

db.AddInParameter(cmd, "DomName", DbType.String, "'xxxxx.net");

exec sp[underscore]executesql N'SELECT * FROM tblDomains WHERE DomainName = @DomName AND DomainID = @Did',
  N'@DomName nvarchar(10),
  @Did int',
  @DomName=N'''xxxxx.net',
  @Did=500204
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top