it-swarm-eu.dev

In che modo un PreparedStatement evita o impedisce l'iniezione di SQL?

So che PreparedStatements evita/impedisce l'iniezione di SQL. Come lo fa? La query del modulo finale costruita utilizzando PreparedStatements sarà una stringa o in altro modo?

107
Prabhu R

Il problema con l'iniezione SQL è che l'input dell'utente viene utilizzato come parte dell'istruzione SQL. Utilizzando istruzioni preparate è possibile forzare l'input dell'utente da gestire come contenuto di un parametro (e non come parte del comando SQL).

Ma se non si utilizza l'input dell'utente come parametro per l'istruzione preparata ma si crea invece il comando SQL unendo le stringhe, si è ancora vulnerabile alle iniezioni di SQL anche quando si utilizzano istruzioni preparate.

66
tangens

Considera due modi per fare la stessa cosa:

PreparedStatement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();

O

PreparedStatement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();

Se "user" proveniva dall'input dell'utente e l'input dell'utente lo era

Robert'); DROP TABLE students; --

Quindi, in prima istanza, verrai bucato. Nel secondo, saresti al sicuro e i tavolini Bobby verrebbero registrati per la tua scuola.

181
Paul Tomblin

Per capire in che modo PreparedStatement impedisce l'iniezione di SQL, è necessario comprendere le fasi dell'esecuzione di query SQL.

1. Fase di compilazione. 2. Fase di esecuzione.

Ogni volta che il motore del server SQL riceve una query, deve passare attraverso le fasi seguenti,

Query Execution Phases

  1. Fase di analisi e normalizzazione: In questa fase, la query viene verificata per sintassi e semantica. Verifica se esistono tabelle di riferimento e colonne utilizzate nella query. Ha anche molte altre attività da svolgere, ma non andiamo nei dettagli.

  2. Fase di compilazione: In questa fase, le parole chiave utilizzate nelle query come select, from, dove etc vengono convertite in un formato comprensibile dalla macchina. Questa è la fase in cui la query viene interpretata e viene decisa l'azione corrispondente da intraprendere. Ha anche molte altre attività da svolgere, ma non andiamo nei dettagli.

  3. Piano di ottimizzazione delle query: In questa fase, l'albero decisionale viene creato per trovare i modi in cui è possibile eseguire la query. Scopre il numero di modi in cui la query può essere eseguita e il costo associato a ciascun modo di eseguire la query. Seleziona il piano migliore per l'esecuzione di una query.

  4. Cache: Il miglior piano selezionato nel piano di ottimizzazione delle query viene archiviato nella cache, in modo che ogni volta che arriva la stessa query, non deve passare attraverso Ancora fase 1, fase 2 e fase 3. Alla successiva interrogazione, la query verrà verificata direttamente nella cache e raccolta da lì per essere eseguita.

  5. Fase di esecuzione: In questa fase, la query fornita viene eseguita e i dati vengono restituiti all'utente come oggetto ResultSet.

Comportamento dell'API PreparedStatement sui passaggi precedenti

  1. PreparedStatements non sono query SQL complete e contengono segnaposto, che in fase di esecuzione vengono sostituiti da dati forniti dall'utente.

  2. Ogni volta che qualsiasi PreparedStatment contenente segnaposto viene passato al motore di SQL Server, passa attraverso le fasi seguenti

    1. Fase di analisi e normalizzazione
    2. Fase di compilazione
    3. Piano di ottimizzazione delle query
    4. Cache (le query compilate con segnaposto vengono archiviate nella cache).

AGGIORNA user set username =? e password =? DOVE ID =?

  1. La query precedente verrà analizzata, compilata con segnaposto come trattamento speciale, ottimizzata e memorizzata nella cache. La query in questa fase è già compilata e convertita in un formato comprensibile dalla macchina. Quindi possiamo dire che la query memorizzata nella cache è precompilata e solo i segnaposto devono essere sostituiti con i dati forniti dall'utente.

  2. Ora in fase di esecuzione quando arrivano i dati forniti dall'utente, le query precompilate vengono raccolte dalla cache e i segnaposto vengono sostituiti con i dati forniti dall'utente.

PrepareStatementWorking

(Ricorda, dopo che i segnaposto sono stati sostituiti con i dati utente, la query finale non viene nuovamente compilata/interpretata e il motore SQL Server tratta i dati utente come dati puri e non come SQL che devono essere analizzati o compilati di nuovo; questa è la bellezza di PreparedStatement.)

Se la query non deve passare nuovamente attraverso la fase di compilazione, tutti i dati sostituiti sui segnaposto vengono trattati come dati puri e non hanno alcun significato per il motore SQL Server ed esegue direttamente la query.

Nota: è la fase di compilazione dopo la fase di analisi, che comprende/interpreta la struttura della query e le dà un comportamento significativo. Nel caso di PreparedStatement, la query viene compilata una sola volta e la query compilata memorizzata nella cache viene sempre raccolta per sostituire i dati utente ed eseguire.

A causa della funzionalità di compilazione di una volta di PreparedStatement, è privo di attacchi SQL Injection.

Puoi ottenere una spiegazione dettagliata con l'esempio qui: http://javabypatel.blogspot.in/2015/09/how-prepared-statement-in-Java-prevents-sql-injection.html

96
Jayesh

L'SQL utilizzato in un PreparedStatement è precompilato sul driver. Da quel momento in poi, i parametri vengono inviati al driver come valori letterali e parti non eseguibili di SQL; quindi nessun SQL può essere iniettato usando un parametro. Un altro effetto collaterale benefico di PreparedStatements (precompilazione + invio solo dei parametri) è il miglioramento delle prestazioni quando si esegue l'istruzione più volte anche con valori diversi per i parametri (supponendo che il driver supporti PreparedStatements) poiché il driver non deve eseguire l'analisi e la compilazione di SQL ciascuna volta che i parametri cambiano.

26
Travis Heseman

La dichiarazione preparata è più sicura. Converte un parametro nel tipo specificato.

Ad esempio stmt.setString(1, user); convertirà il parametro user in una stringa.

Supponiamo che il parametro contenga una stringa SQL contenente un comando eseguibile: l'uso di un'istruzione preparata non lo consentirà.

Aggiunge metacarattere (a.k.a. conversione automatica) a quello.

Questo lo rende più sicuro.

3
Guru R Handa

I indovina sarà una stringa. Ma i parametri di input verranno inviati al database e verranno applicati cast/conversioni appropriati prima di creare un'istruzione SQL effettiva.

Per fare un esempio, potrebbe provare a vedere se CAST/Conversion funziona.
Se funziona, potrebbe crearne una dichiarazione finale.

   SELECT * From MyTable WHERE param = CAST('10; DROP TABLE Other' AS varchar(30))

Prova un esempio con un'istruzione SQL che accetta un parametro numerico.
Ora prova a passare una variabile stringa (con contenuto numerico accettabile come parametro numerico). Suscita qualche errore?

Ora prova a passare una variabile stringa (con contenuto non accettabile come parametro numerico). Guarda cosa succede?

3
shahkalpesh

Iniezione SQL: quando l'utente ha la possibilità di inserire qualcosa che potrebbe far parte dell'istruzione sql

Per esempio:

Stringa query = "INSERIRE IN VALORI studenti (" "+ utente +" ")"

quando l'utente inserisce "Robert"); Studenti DROP TABLE; - "come input, causa l'iniezione SQL

Quanto affermazione preparata impedisce questo?

String query = "INSERT INTO student VALUES (" "+": name "+" "")

parametri.addValue ("nome", utente);

=> quando l'utente inserisce nuovamente "Robert"; Studenti DROP TABLE; - “, la stringa di input è precompilata sul driver come valori letterali e immagino che possa essere lanciata come:

CAST ( ‘Robert’); Studenti DROP TABLE; - "AS varchar (30))

Quindi, alla fine, la stringa verrà letteralmente inserita come nome nella tabella.

http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection/

2
jack

Come spiegato in questo post , il solo PreparedStatement non ti aiuta se stai ancora concatenando le stringhe.

Ad esempio, un attaccante canaglia può ancora fare quanto segue:

  • chiamare una funzione sleep in modo che tutte le connessioni al database siano occupate, rendendo quindi l'applicazione non disponibile
  • estrazione di dati sensibili dal DB
  • ignorando l'autenticazione utente

Non solo SQL, ma anche JPQL o HQL possono essere compromessi se non si utilizzano i parametri di bind.

In conclusione, non si dovrebbe mai usare la concatenazione di stringhe durante la creazione di istruzioni SQL. Utilizzare un'API dedicata a tale scopo:

1
Vlad Mihalcea

Discorso preparato:

1) La precompilazione e la memorizzazione nella cache lato DB dell'istruzione SQL consentono un'esecuzione complessivamente più rapida e la possibilità di riutilizzare la stessa istruzione SQL in batch.

2) Prevenzione automatica degli attacchi di iniezione SQL mediante escape incorporato di virgolette e altri caratteri speciali. Si noti che ciò richiede l'utilizzo di uno dei metodi setXxx () di PreparedStatement per impostare il valore.

1
Mukesh Kumar