I parametri sono davvero sufficienti per prevenire le iniezioni di Sql?

Ho predicato sia ai miei colleghi che a SO sulla bontà dell’uso dei parametri nelle query SQL, specialmente nelle applicazioni .NET. Sono persino andato così lontano da prometterli come dare l’immunità dagli attacchi SQL injection.

Ma sto iniziando a chiedermi se questo è davvero vero. Esistono attacchi di SQL injection noti che avranno esito positivo rispetto a una query parametrizzata? Puoi ad esempio inviare una stringa che provoca un overflow del buffer sul server?

Ci sono ovviamente altre considerazioni da fare per garantire che un’applicazione web sia sicura (come la disinfezione degli input dell’utente e tutte quelle cose) ma ora sto pensando alle iniezioni SQL. Sono particolarmente interessato agli attacchi contro MsSQL 2005 e 2008 poiché sono i miei database principali, ma tutti i database sono interessanti.

Modifica: per chiarire cosa intendo per parametri e query parametrizzate. Usando i parametri intendo l’uso di “variabili” invece di build la query sql in una stringa.
Quindi, invece di fare questo:

SELECT * FROM Table WHERE Name = 'a name' 

Facciamo questo:

 SELECT * FROM Table WHERE Name = @Name 

e quindi impostare il valore del parametro @Name sull’object query / comando.

I segnaposto sono sufficienti per evitare iniezioni. Potresti essere ancora aperto al buffer overflow, ma quello è un altro tipo di attacco da un’iniezione SQL (il vettore di attacco non sarebbe la syntax SQL ma binario). Dal momento che i parametri passati verranno tutti debellati correttamente, non c’è alcun modo per un utente malintenzionato di passare dati che verranno trattati come SQL “live”.

Non è ansible utilizzare le funzioni all’interno dei segnaposto e non è ansible utilizzare i segnaposto come nomi di colonne o tabelle, poiché sono sfuggiti e vengono citati come valori letterali stringa.

Tuttavia, se si utilizzano i parametri come parte di una concatenazione di stringhe all’interno della query dynamic, si è ancora vulnerabili all’iniezione, poiché le stringhe non verranno sfuggite ma saranno letterali. L’utilizzo di altri tipi per i parametri (come il numero intero) è sicuro.

Detto questo, se stai usando l’input di utilizzo per impostare il valore di qualcosa come security_level , allora qualcuno potrebbe semplicemente farsi amministratori nel tuo sistema e avere un free-for-all. Ma questa è solo la convalida dell’input di base e non ha nulla a che fare con l’iniezione SQL.

No, esiste ancora il rischio di SQL injection ogni volta che si interpolano dati non convalidati in una query SQL.

I parametri di query aiutano a evitare questo rischio separando i valori letterali dalla syntax SQL.

 'SELECT * FROM mytable WHERE colname = ?' 

Va bene, ma ci sono altri scopi di interpolazione dei dati in una query SQL dynamic che non può utilizzare parametri di query, perché non è un valore SQL ma piuttosto un nome di tabella, nome di colonna, espressione o qualche altra syntax.

 'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')' ' ORDER BY ' + @colname' 

Non importa se stai usando stored procedure o esegui query SQL dinamiche direttamente dal codice dell’applicazione. Il rischio è ancora lì.

Il rimedio in questi casi è di impiegare FIEO se necessario:

  • Input filtro: verifica che i dati appaiano come numeri interi legittimi, nomi di tabelle, nomi di colonne e così via prima di interpolarli.

  • Uscita di fuga: in questo caso “uscita” significa mettere i dati in una query SQL. Utilizziamo le funzioni per trasformare le variabili utilizzate come stringhe letterali in un’espressione SQL, in modo che le virgolette e gli altri caratteri speciali all’interno della stringa vengano sfuggiti. Dovremmo anche usare le funzioni per trasformare le variabili che sarebbero usate come nomi di tabelle, nomi di colonne, ecc. Come per altre syntax, come scrivere dynamicmente intere espressioni SQL, si tratta di un problema più complesso.

Sembra esserci una certa confusione in questa discussione sulla definizione di una “query parametrizzata”.

  • SQL come un proc memorizzato che accetta parametri.
  • SQL chiamato utilizzando la raccolta Parametri DBMS.

Data la precedente definizione, molti link mostrano attacchi di lavoro.

Ma la definizione “normale” è quest’ultima. Data questa definizione, non conosco alcun attacco di iniezione SQL che funzioni. Ciò non significa che non ce ne sia uno, ma devo ancora vederlo.

Dai commenti, non mi sto esprimendo abbastanza chiaramente, quindi ecco un esempio che si spera sia più chiaro:

Questo approccio è aperto all’iniezione SQL

 exec dbo.MyStoredProc 'DodgyText' 

Questo approccio non è aperto all’iniezione SQL

 using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection)) { cmd.CommandType = CommandType.StoredProcedure; SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar); newParam.Value = "DodgyText"; ..... cmd.Parameters.Add(newParam); ..... cmd.ExecuteNonQuery(); } 

qualsiasi parametro sql del tipo stringa (varchar, nvarchar, ecc.) utilizzato per build una query dynamic è ancora vulnerabile

in caso contrario la conversione del tipo di parametro (ad esempio int, decimale, data, ecc.) dovrebbe eliminare qualsiasi tentativo di iniettare sql tramite il parametro

EDIT: un esempio, dove parametro @ p1 è destinato ad essere un nome di tabella

 create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) AS SET NOCOUNT ON declare @sql varchar(512) set @sql = 'select * from ' + @p1 exec(@sql) GO 

Se @ p1 è selezionato da un elenco a discesa, è un potenziale vettore di attacco di sql-injection;

Se @ p1 è formulato programmaticamente senza la capacità dell’utente di intervenire, non è un potenziale vettore di attacco per l’iniezione di sql

Un buffer overflow non è SQL injection.

Le query parametrizzate garantiscono la sicurezza contro l’iniezione SQL. Non garantiscono che non ci siano exploit sotto forma di bug nel server SQL, ma nulla lo garantirà.

I tuoi dati non sono sicuri se usi sql dinamico in qualsiasi modo forma o modulo perché le autorizzazioni devono essere a livello di tabella. Sì, hai limitato il tipo e la quantità di attacco per iniezione da quella particolare query, ma non limitato l’accesso che un utente può ottenere se trova un modo nel sistema e sei completamente incline agli utenti interni che accedono a ciò che non dovrebbero per commettere frodi o rubare informazioni personali da vendere. SQL dinamico di qualsiasi tipo è una pratica pericolosa. Se si utilizzano proc stored non dinamici, è ansible impostare le autorizzazioni al livello procesdure e nessun utente può eseguire operazioni diverse da quelle definite dai proc (ad eccezione degli amministratori di sistema, ovviamente).

È ansible che un processo memorizzato sia vulnerabile a tipi speciali di iniezione SQL tramite overflow / troncamento, vedere: Iniezione abilitata dal Troncamento dati qui:

http://msdn.microsoft.com/en-us/library/ms161953.aspx

Ricorda che con i parametri puoi facilmente memorizzare la stringa, o dire username se non hai alcuna politica, “); drop users users; -”

Questo di per sé non causerà alcun danno, ma è meglio sapere dove e in che modo tale data viene utilizzata ulteriormente nella tua applicazione (ad esempio, memorizzata in un cookie, recuperata in seguito per fare altre cose.

È ansible eseguire SQL dinamico come esempio

 DECLARE @SQL NVARCHAR(4000); DECLARE @ParameterDefinition NVARCHAR(4000); SELECT @ParameterDefinition = '@date varchar(10)' SET @SQL='Select CAST(@date AS DATETIME) Date' EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'