2008-08-18 16 views
6

.NET, Java e altre API di database di alto livello in varie lingue spesso forniscono tecniche note come istruzioni preparate e associazione di parametri anziché inviare comandi di testo normale al server Database. Quello che vorrei sapere è ciò che accade quando si esegue una dichiarazione come questa:Parameter Binding: cosa succede sotto il cofano?

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 pratica migliore. Gli attacchi di SQL injection sono ridotti al minimo in questo modo. Ma cosa succede esattamente quando si eseguono queste affermazioni? Il risultato finale è ancora una stringa SQL sicura? In caso contrario, qual è il risultato finale? E questo è sufficiente per prevenire attacchi di SQL injection?

risposta

5

The MySQL manual page sulle dichiarazioni preparate fornisce molte informazioni (che dovrebbero applicarsi a qualsiasi altro RDBMS).

In sostanza, l'istruzione viene analizzata ed elaborata in anticipo e i parametri vengono inviati separatamente anziché essere gestiti insieme al codice SQL. Ciò elimina gli attacchi di SQL-injection perché l'SQL viene analizzato prima ancora che i parametri siano impostati.

0

Se si utilizza MS SQL, caricare il profiler e verranno visualizzate le istruzioni SQL generate quando si utilizzano query parametrizzate. Ecco un esempio (sto usando Enterprise Libary 3.1, ma i risultati sono gli stessi che utilizzano SqlParameters direttamente) contro 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 

Inoltre potrai vedere qui, se i caratteri virgolette sono stati passati come parametri, essi sono fuggiti di conseguenza:

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 
0

in termini profani: se una dichiarazione preparata viene inviata poi il DB userà un piano se è disponibile, non è così, non è necessario ricreare un piano ogni volta che questa query viene inviata ma solo i valori dei parametri sono cambiati. questo è molto simile a come funzionano i proc, l'ulteriore vantaggio con proc è che puoi dare il permesso solo tramite proc e non alle tabelle sottostanti a tutti