Associazione dei parametri:Cosa succede sotto il cofano?
Domanda
.NET, Java e altre API di database di alto livello in vari linguaggi spesso forniscono tecniche note come istruzioni preparate e associazione di parametri anziché inviare comandi di testo semplice al server del database.Quello che vorrei sapere è cosa succede quando esegui un'istruzione come questa:
SqlCommand cmd = new SqlCommand("GetMemberByID");
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter("@ID", memberID);
para.DbType = DbType.Integer;
cmd.Parameters.Add(param);
So che questa è una buona pratica.Gli attacchi SQL injection vengono ridotti al minimo in questo modo.Ma cosa succede esattamente dietro le quinte quando esegui queste affermazioni?Il risultato finale è ancora una stringa sicura SQL?In caso contrario, qual è il risultato finale?E questo è sufficiente per prevenire attacchi SQL injection?
Soluzione
La pagina del manuale MySQL sulle dichiarazioni preparate fornisce molte informazioni (che dovrebbero applicarsi a qualsiasi altro RDBMS).
Fondamentalmente, la tua istruzione viene analizzata ed elaborata in anticipo e i parametri vengono inviati separatamente invece di essere gestiti insieme al codice SQL.Ciò elimina gli attacchi SQL injection perché l'SQL viene analizzato prima ancora che i parametri vengano impostati.
Altri suggerimenti
in parole povere:se viene inviata un'istruzione preparata, il DB utilizzerà un piano se disponibile, non è necessario ricreare un piano ogni volta che viene inviata questa query ma sono cambiati solo i valori dei parametri.questo è molto simile a come funzionano i procs, l'ulteriore vantaggio di procs è che puoi dare il permesso solo tramite procs e non alle tabelle sottostanti
Se utilizzi MS SQL, carica il profiler e vedrai quali istruzioni SQL vengono generate quando utilizzi query con parametri.Ecco un esempio (sto utilizzando Enterprise Libary 3.1, ma i risultati sono gli stessi utilizzando direttamente SqlParameters) rispetto a 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);
}
Questo 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
Puoi anche vedere qui, se i caratteri delle virgolette sono stati passati come parametri, vengono di conseguenza sottoposti a escape:
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