2010-01-05 10 views
8

Ho un'istruzione SQL simile a quella mostrata di seguito in Perl:Come posso evitare le virgolette singole e doppie nell'istruzione SQL preparata?

my $sql="abc..TableName '$a','$b' "; 

Il $ a è testo libero che può contenere qualsiasi cosa, compreso virgolette singole, doppi apici, personaggi di back e front-slash, etc.

Come possono essere fatti sfuggire questi caratteri per far funzionare l'istruzione SQL?

Grazie.

+3

'$ a' e' $ b' hanno un significato speciale relativo alla funzione 'sort'. In genere non è una buona idea usarli. Tranne i nomi di variabili brevi in ​​un esempio di codice. – daotoad

+0

Oltre al tag [perl], dup di [Il modo migliore per interrompere SQL Injection in PHP] (http://stackoverflow.com/q/60174/90527). L'unica differenza pratica si trova negli esempi di codice. Inoltre, dup di [Qual è il modo migliore per evitare attacchi di SQL injection?] (Http://stackoverflow.com/q/1973/). – outis

risposta

21

È possibile utilizzare il metodo ->quote (supponendo che si sta utilizzando DBI):

my $oldValue = $dbh->quote('oldValue'); 
my $newValue = $dbh->quote('newValue'); 
$dbh->do("UPDATE myTable SET myValue=$newValue where myValue=$oldValue"); 

Meglio ancora, la pratica migliore è quella di utilizzare i valori bind:

my $sth = $dbh->prepare('UPDATE myTable SET myValue=? WHERE myValue=?'); 

$sth->execute('newValue','oldValue'); 

Questo dovrebbe funzionare anche per le chiamate stored procedure, assumendo l'istruzione una volta che le stringhe sono state espanse è valido SQL. Questo potrebbe essere specifico per driver/DB, quindi YMMV.

my $sth = $dbh->prepare("DBName..ProcName ?,? "); 
$sth->execute($a, $b); 
+0

Mi dispiace per non essere stato chiaro. Sto effettuando una chiamata a una stored procedure. L'esempio dovrebbe essere qualcosa di simile qui sotto: my $ sql = "DBName..ProcName '$ a', '$ b'"; – Sam

+5

L'utilizzo dei parametri di bind dovrebbe continuare a funzionare per le chiamate di procedura memorizzate. – mopoke

+0

E nel caso non sia ovvio, se hai utilizzato i parametri di bind E hai eseguito manualmente l'escape di virgolette singole sui tuoi valori prima di eseguire l'inserimento, il valore della colonna finirà con due virgolette singole sequenziali per ogni singola quota. – RTF

9

Utilizzare una dichiarazione preparata. Sostituisci la variabile con un?. Per citare un esempio dalle manpage DBI:

$sql = 'SELECT * FROM people WHERE lastname = ?'; 
$sth = $dbh->prepare($sql); 
$sth->execute($user_input_here); 

L'interpolazione dell'input dell'utente nel SQL richiede buchi di sicurezza.

+0

Mi dispiace per non essere stato chiaro. Sto effettuando una chiamata a una stored procedure. L'esempio dovrebbe essere stato qualcosa di seguito: my $ sql = "DBName..ProcName '$ a', '$ b'"; – Sam

6

Se si utilizzano i segnaposto dei parametri di query, non è necessario sfuggire al contenuto delle stringhe.

my $sql="DBName..ProcName ?, ?"; 
$sth = $dbh->prepare($sql); 
$sth->execute($a, $b); 

Se la DBI sta usando parametri di query veri, invia i valori dei parametri per il RDBMS separatamente dal SQL. I valori non vengono mai combinati con la stringa dell'istruzione SQL, pertanto i valori non hanno mai l'opportunità di causare l'iniezione SQL.

Se il DBI sta "emulando" istruzioni preparate interpolando le variabili nella stringa di query, DBI dovrebbe gestire la logica di escape corretta in modo da non doverlo fare. Lascia che gli esperti (quelli che scrivono e testano DBI) si preoccupino di come farlo.

3

Se non si desidera utilizzare -> citazione (per qualche ragione, questa funzione non funziona sulla mia versione di DBI) quindi provare questo:

$query=~s/\"/\\\"/g; 

tendo a fare lo stesso con singole virgolette e virgole anche solo per essere al sicuro.

Sembra funzionare bene per me ...!

Problemi correlati