In che modo la stored procedure impedisce l'iniezione SQL?

10

Forse non sono molto chiaro riguardo alla stored procedure. Qualcuno può spiegarmi come la stored procedure impedisce l'iniezione SQL con un semplice esempio di MySql.

    
posta Anandu M Das 01.10.2014 - 08:12
fonte

4 risposte

12

Le stored procedure sono una forma di query parametrizzata. Il problema fondamentale che causa l'iniezione SQL sono i dati trattati come linguaggio di query.

$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";

In questo esempio, se imposto $password su foo' OR 'x'='x , otteniamo questo:

SELECT * FROM users WHERE username = 'blah' AND password = 'foo' OR 'x'='x'

Poiché il carattere 'x' è sempre uguale al carattere 'x', questa query restituirà sempre le righe indipendentemente dal fatto che l'utente / passaggio sia corretto. Il database non può sapere che non l'hai inteso, perché viene assegnato solo una stringa senza contesto.

Per evitare ciò, devi essere in grado di conoscere la differenza tra la query e i dati. Le procedure memorizzate risolvono questo problema scrivendo la query in anticipo, con i marcatori per i parametri, in modo che i dati possano essere passati in seguito. Ad esempio:

SELECT * FROM users WHERE username = ? AND password = ?

Il driver del database invia il nome di questa stored procedure (o, nelle query parametriche standard, solo il testo della query stesso) e un elenco di parametri, come distinte entità separate nel protocollo. Ciò significa che il server di database può analizzare la stringa di query come linguaggio di query in modo sicuro e trattare i parametri esclusivamente come dati, senza alcuna ambiguità.

Ho anche ha scritto più a lungo rispondi un po 'indietro che spiega tutto ciò in modo più dettagliato, se ti è utile.

    
risposta data 01.10.2014 - 11:03
fonte
4

Le procedure memorizzate non sono immuni all'iniezione SQL . Come spiegato qui:

link

Finché è possibile creare SQL dinamico all'interno delle stored procedure, sei vulnerabile all'iniezione SQL.

E MySQL a partire dalla 5.0.13 in poi, hanno funzionalità SQL dinamiche:

link

E quindi vulnerabile all'iniezione SQL.

Nel server SQL , ecco un esempio:

link

VULNERABLE STORED PROCEDURE USING EXEC STATEMENT.
CREATE PROCEDURE getDescription
   @vname VARCHAR(50)
AS
   EXEC('SELECT description FROM products WHERE name = '''+@vname+ '''')
RETURN

E un altro esempio:

VULNERABLE STORED PROCEDURE USING DYNAMIC CURSOR.
CREATE PROCEDURE printDescriptions
   @vname             VARCHAR(100)
AS
   DECLARE @vdesc VARCHAR(1000)
   DECLARE @vsql VARCHAR(4000)
   SET @vsql = 'SELECT description FROM products WHERE name='''+@vname+''''
   DECLARE cur CURSOR FOR EXEC @vsql

   OPEN cur
   FETCH NEXT FROM cur INTO @vdesc

   WHILE @@FETCH_STATUS = 0
   BEGIN
      PRINT @vdesc
      FETCH NEXT FROM cur INTO @vdesc
   END

   CLOSE cur
   DEALLOCATE cur
RETURN

E in Oracle , ecco gli esempi:

link

link

La precedente presentazione di David Litchfield in Blackhat Europe ha qualcosa di più serio, dall'iniezione SQL può portare all'escalation dei privilegi - quindi un normale utente Oracle può essere eseguito come un DBA se le stored procedure sono create da DBA (ad es. tutti gli oggetti di sistema di Oracle).

    
risposta data 12.01.2017 - 07:04
fonte
3

Un database SQL esegue una dichiarazione in diversi passaggi. All'inizio viene analizzato il test dell'istruzione SQL, dopo di che verrà ottimizzato e compilato. Al termine, il database dispone ora di un software interno in grado di eseguire l'istruzione SQL fornita.

Le stored procedure sono precompilate. In altre parole, il database crea quel pezzo di software interno prima di usarlo. In questo caso, solo il codice di programma viene interpretato senza alcuna influenza dei parametri.

Se si passa un parametro completo dell'istruzione SQL completo al database, esso elabora i passaggi sopra descritti.

Per esempio ...

SELECT * FROM myTable WHERE id=1

o dai qualcosa di simile ...

SELECT * FROM myTable WHERE id=1;DROP TABLE myTable

Normalmente nessuno scriverà una dichiarazione come la seconda nel suo codice di programma, ma se si prendono ad esempio parametri diretti da una richiesta web, è possibile che una dichiarazione come quella risulta.

var sqlString="SELECT * FROM myTable WHERE id=";
sqlString = sqlString+request.getParameter("id");
// database parse, compile and optimize
var result=database.doQuery(sqlString);

Se si utilizzano stored procedure o istruzioni preparate. Il processo di analisi e compilazione è già fatto nel database. Tutta l'interpretazione dipende dal tuo codice di programma. Quando lo chiami, il database inserisce solo i parametri dati nel codice precompilato e ne fornisce i tipi di dati eccepiti.

var sqlString = "call queryMyTable(?)";
// get the precompiled statement from database
var statement = database.createStatement(sqlString);
// inject the parameter
statement.setParameter(1,request.getParameter("id"));
// if 'id' is a number it works fine ...
// but if 'id' is '1;DROP TABLE myTable' you will got a type cast error and the risk of SQL injection is banned
var result = statement.execute();

Le stored procedure e le istruzioni preparate sono in vista della sicurezza uguale.

    
risposta data 01.10.2014 - 09:40
fonte
0

Un altro modo per pensarci, per essere espliciti e aumentare le risposte già fornite.

SELECT * FROM users WHERE username = 'blah' AND password = 'foo' OR 'x'='x'

Senza la dichiarazione preparata il OR dopo che "foo" è stato trattato come codice

Ora, con l'istruzione preparata, OR (e tutto il resto) dopo "pippo" viene trattato come dati

    
risposta data 27.03.2018 - 19:23
fonte

Leggi altre domande sui tag