2009-02-12 15 views
82

Ho sentito che "tutti" utilizzano query SQL parametrizzate per proteggersi dagli attacchi di SQL injection senza dover vailidare ogni singolo input dell'utente.Come si crea una query SQL con parametri? Perché dovrei?

Come si fa? Lo ottieni automaticamente quando usi le stored procedure?

Quindi la mia comprensione questo è senza parametri:

cmdText = String.Format("SELECT foo FROM bar WHERE baz = '{0}'", fuz) 

questo sarebbe parametrizzare?

cmdText = String.Format("EXEC foo_from_baz '{0}'", fuz) 

Oppure ho bisogno di fare qualcosa di più esteso come questo al fine di proteggermi dall'iniezione SQL?

With command 
    .Parameters.Count = 1 
    .Parameters.Item(0).ParameterName = "@baz" 
    .Parameters.Item(0).Value = fuz 
End With 

Ci sono altri vantaggi nell'utilizzo di query parametrizzate oltre alle considerazioni sulla sicurezza?

Aggiornamento: Questo fantastico articolo è stato collegato in una delle domande di riferimenti di Grotok. http://www.sommarskog.se/dynamic_sql.html

+0

Ho trovato scioccante che a quanto pare questa domanda non è stata posta prima su Stackoverflow. Molto buono! –

+3

Oh, ha. Formulato in modo molto diverso, ovviamente, ma è così. –

+0

Si prega di non utilizzare il blocco "Con". Mai. "With" è una delle ragioni per cui così tante persone hanno una forte antipatia per VB. – yfeldblum

risposta

67

Il vostro esempio EXEC non sarebbe parametrizzato. Hai bisogno di query con parametri (istruzioni preparate in alcuni ambienti) per evitare di input come questo da causando danni:

'; GOCCIA bar TABLE; -

provare a mettere che nella variabile fuz (o don se consideri il tuo tavolo da bar). Sono possibili anche domande più sottili e dannose.

Ecco un esempio di come si fa parametri con SQL Server:

Public Function GetBarFooByBaz(ByVal Baz As String) As String 
    Dim sql As String = "SELECT foo FROM bar WHERE baz= @Baz" 

    Using cn As New SqlConnection("Your connection string here"), _ 
     cmd As New SqlCommand(sql, cn) 

     cmd.Parameters.Add("@Baz", SqlDbType.VarChar, 50).Value = Baz 
     Return cmd.ExecuteScalar().ToString() 
    End Using 
End Function 

Le stored procedure sono talvolta accreditati con prevenire SQL injection. Tuttavia, la maggior parte delle volte è ancora necessario chiamarli utilizzando i parametri di query o non aiutano. Se si utilizzano le stored procedure esclusivamente, è possibile disattivare le autorizzazioni per SELECT, UPDATE, ALTER, CREATE, DELETE, ecc. (Quasi tutto tranne EXEC) per l'account utente dell'applicazione e ottenere una protezione in questo modo.

+0

Puoi spiegare ulteriormente questo 'cmd.Parameters.Add (" @ Baz ", SqlDbType.VarChar, 50) .Valore = Baz' per favore? –

+1

@CaryBondoc, cosa vuoi sapere? Quella linea crea un parametro chiamato '@ Baz' che è di tipo' varchar (50) 'a cui è assegnato il valore della stringa' Baz'. –

+0

si potrebbe anche dire "command.parameters.addiwthvalue (" @ Baz ", 50)" –

5

Si vuole andare con il tuo ultimo esempio in quanto questo è l'unico che è veramente parametrizzato. Oltre ai problemi di sicurezza (che sono molto più diffusi di quanto si possa pensare) è meglio lasciare ADO.NET a gestire la parametrizzazione in quanto non si può essere sicuri che il valore che si sta trasmettendo richieda singole virgolette attorno o no senza ispezionare lo Type di ogni parametro.

[Edit] Ecco un esempio:

SqlCommand command = new SqlCommand(
    "select foo from bar where baz = @baz", 
    yourSqlConnection 
); 

SqlParameter parameter = new SqlParameter(); 
parameter.ParameterName = "@baz"; 
parameter.Value = "xyz"; 

command.Parameters.Add(parameter); 
+3

In questo modo: le stringhe .Net sono unicode, pertanto il parametro assumerà NVarChar per impostazione predefinita.Se è davvero una colonna VarChar, ciò può causare grossi problemi di prestazioni. –

1

Il testo di comando devono essere come:

cmdText = "SELECT foo FROM bar WHERE baz = ?" 

cmdText = "EXEC foo_from_baz ?" 

Quindi aggiungere i valori dei parametri.In questo modo assicura che il valore con finiscono solo per essere utilizzato come un valore, mentre con l'altro metodo se fuz variabile è impostata su

"x'; delete from foo where 'a' = 'a" 

si può vedere che cosa potrebbe accadere?

2

La maggior parte delle persone lo farebbe attraverso una libreria di linguaggio di programmazione lato server, come PDO di PHP o DDI di Perl.

Per esempio, in PDO:

$dbh=pdo_connect(); //you need a connection function, returns a pdo db connection 

$sql='insert into squip values(null,?,?)'; 

$statement=$dbh->prepare($sql); 

$data=array('my user supplied data','more stuff'); 

$statement->execute($data); 

if($statement->rowCount()==1){/*it worked*/} 

Questo si prende cura di sfuggire i dati per l'inserimento del database.

Un vantaggio è che è possibile ripetere un inserimento molte volte con una dichiarazione preparata, ottenendo un vantaggio di velocità.

Ad esempio, nella query precedente potrei preparare l'istruzione una volta e quindi ripetere il ciclo creando l'array di dati da un gruppo di dati e ripetere l'operazione -> eseguire tutte le volte necessarie.

14

Decisamente il secondo.

query parametrizzate hanno due vantaggi principali:

  • sicurezza: E 'un buon modo per evitare SQL Injection vulnerabilità
  • Performance: Se si richiama regolarmente la stessa query solo con parametri diversi di una query parametrizzata potrebbe consentire la database per memorizzare le tue query, che è una notevole fonte di guadagno in termini di prestazioni.
  • Extra: non dovrai preoccuparti di problemi di formattazione di data e ora nel codice del tuo database. Allo stesso modo, se il tuo codice verrà mai eseguito su macchine con impostazioni internazionali non inglesi, non avrai problemi con i punti decimali/virgole decimali.
+0

Spero che questo post sia stato riscritto quando "il secondo" era qualcos'altro. Allo stato attuale, questa risposta è completamente sbagliata! –

Problemi correlati