Come evitare iniezioni SQL lato DB in SQLServer, Oracle, MySQL
Come evitare iniezione SQL: lato SQL Server (SP_EXECUTESQL)
In generale va evitato nel modo più assoluto la scrittura di query sql diamiche.Va evitato cioè l’uso lato SQL Server di sp_executesql e EXEC
Di seguito mostriamo come trasformare una query “dinamica” in una “statica”
CREATE PROCEDURE search_orders @custid nchar(5) = NULL, @shipname nvarchar(40) = NULL AS DECLARE @sql nvarchar(4000) SELECT @sql = ' SELECT OrderID, OrderDate, CustomerID, ShipName ' + ' FROM dbo.Orders WHERE 1 = 1 ' IF @custid IS NOT NULL SELECT @sql = @sql + ' AND CustomerID LIKE ''' + @custid + '''' IF @shipname IS NOT NULL SELECT @sql = @sql + ' AND ShipName LIKE ''' + @shipname + '''' EXEC(@sql) ...
In tale esempio, a fronte di un form con parametri opzionali come custid e shipname, viene erroneamente utilizzata una query dinamica. Il modo corretto di procedere è invece il seguente.
1 Definire la stored procedure come:
CREATE PROCEDURE search_orders @custid nchar(5) = NULL, @shipname nvarchar(40) = NULL AS DECLARE @sql nvarchar(4000) SELECT OrderID, OrderDate, CustomerID, ShipName FROM dbo.Orders WHERE ((@custid IS NULL) OR (CustomerID like @custid)) AND ((@shipname IS NULL) OR (ShipName LIKE @shipname)) ....
2 Far sì che la stored procedure va chiamata attraverso l’uso dei Parameters descritti nel paragrafo precedente.
La query così definita ha i seguenti vantaggi:
- E’ molto sicura
- E’ facile da mantenere (per esempio per aggiungere/togliere condizioni)
- E’ compilata come stored procedure, e quindi il suo piano di esecuzione viene ottimizzato dopo ogni esecuzione (una query passata ad EXEC è interpretata, compilata, ecc ogni volta e molte versioni di SQL Server di norma non mantengono il piano di esecuzione di una query on the fly)
- Poiché le condizioni in OR sono facili da verificare, il database ottimizza automaticamente la query a fronte degli input, evitando le verifiche inutili. Per esempio se sono nulli entrambi gli input, il database effettua una semplice query SELECT OrderID, OrderDate, CustomerID, ShipName FROM dbo.Orders
- Non dipende da estensioni proprietarie e quindi è più facile da migrare a differenti versioni di SQL Server o di Oracle.
- E’ facile da leggere, capire e trascrivere.
Per maggiori informazioni
- The Curse and Blessings of Dynamic SQL, http://www.sommarskog.se/dynamic_sql.html
- OWASP Top ten https://owasp.org/www-project-top-ten/2017/A1_2017-Injection
- How To: Protect From SQL Injection in ASP.NET, http://msdn.microsoft.com/en-us/library/ff648339
- Optional Parameters in SQL Stored Procedures, http://weblogs.asp.net/rmclaws/archive/2004/02/18/75381.aspx