Prevenzione dell’iniezione SQL in .NET

In genere, scrivo il mio SQL in questo modo in .NET

sql.Append("SELECT id, code, email FROM mytable WHERE variable = @variable "); 

Quindi fai qualcosa del genere:

 using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["defaultConnection"]].ConnectionString)) { using (SqlCommand myCommand = new SqlCommand(sql.ToString(), conn)) { myCommand.Parameters.AddWithValue("@variable", myVariableName"); ... 

Ma dovrei anche fare questo addParameter quando i dati che ho ricevuto provengono direttamente dal database in questo modo?

 likesql.Append(string.Format("SELECT group_id, like_text FROM likeTerms ORDER BY group_id ASC ")); DataTable dtLike = SqlHelper.GetDataTable(likesql.ToString()); foreach (DataRow dr in dtLike) { buildsql.Append(".... varId = " + dr["group_id"].ToString() + "..."); ... 

È accettabile? Qual è la migliore pratica?

Devi sempre usare i parametri:

  • Da dove provengono i valori nel tuo database?
  • Puoi fidarti, nel tuo esempio, che ‘group_id’ non è stato modificato per essere qualcosa che non ti aspetti?

Non fidarti di nessuno

Qualcuno con accesso limitato al database può iniettare direttamente in un campo utilizzato altrove?

Prestazione

Inoltre, aiuta le prestazioni. I piani di esecuzione memorizzati nella cache ignoreranno il valore del parametro, il che significa che stai salvando il server dalla ricompilazione della query ogni volta che i parametri cambiano.

Quando si utilizzano DbCommands con parametri, i parametri non sono mai “in linea” nella query. Invece, la query ei dati dei parametri vengono passati a una stored procedure di sistema speciale, sp_executesql. Quando viene eseguito in questo modo, qualsiasi dato di parametro che si possiede viene trattato esattamente come tale e non viene analizzato dalla stringa di query; pertanto, un comando iniettato che potrebbe aver superato la convalida non viene mai eseguito.

L’utilizzo dei parametri è la procedura migliore per i livelli di accesso ai dati basati su ADO.NET, indipendentemente da dove provengano i dati, e IMO è l’unico modo in cui dovrebbe essere eseguito a questo livello (se non si utilizza un ORM). Non devi MAI concatenare valori recuperati da un modulo Web o Windows in un’istruzione SQL e, se segui questa regola, perché dovresti implementarla in modo diverso solo perché sei sicuro o addirittura sicuro che le informazioni non siano direttamente da parte dell’utente? Segui lo stesso schema e se e quando esporti quel metodo per mantenere i dati specificati dall’utente non verrai bruciato.

È accettabile (nel senso se conosci le restrizioni a volte potresti funzionare correttamente).

È buona norma utilizzare i valori dal database e creare query SQL con concatenazione di stringhe – no.

Nel tuo esempio, cosa succede se “group_id” è "'--" ?

Io raccomando di usare la procedura memorizzata, ma questo è accettabile, mi raccomando anche di disinfettare i parametri prima di assegnarli alla query