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”

 
[sql]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)[/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:

 
[sql]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))[/sql]
….

 

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:

  1. E’ molto sicura
  2. E’ facile da mantenere (per esempio per aggiungere/togliere condizioni)
  3. 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)
  4. 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
  5. Non dipende da estensioni proprietarie e quindi è più facile da migrare a differenti versioni di SQL Server o di Oracle.
  6. E’ facile da leggere, capire e trascrivere.

 

Per maggiori informazioni

Leave a Reply