2012-06-20 12 views
7

so circa gli usi di parametri in frasi SQL, ma solo per curiosità è sicuro da usare la funzione di formattazione per evitare iniezioni SQL invece uso paramters.Formato funzione vs Parametri in scenari di iniezione sql?

come questo campione

sCustomer : string 
begin 
AdoSql.CommandText:=Format('Select SUM(value) result from invoices where customer=%s',[QuotedStr(sCustomer)]); 
end; 
+1

penso titolo avrebbe dovuto essere 'funzione QuotedStr vs Parametri in scenari di SQL injection?', Ma cambiarla, si romperà alcune risposte qui. il * problema * qui riguarda 'QuotedStr' e non' Format'. – kobik

risposta

11

Sarebbe probabilmente essere sicuro contro SQL injection, assumendo QuotedStr funziona come previsto e non ci sono casi limite che si possono rompere esso. (Che è in alcun modo garantita. Come Linas ha sottolineato in un commento, MySql consente di utilizzare \' a scappare citazioni. Altri DBMS probabilmente hanno funzionalità simili. Un utente malintenzionato con abbastanza conoscenza teorica del sistema sarebbe in grado di sfruttarle.)

Tuttavia, anche se QuotedStr era abbastanza buono, è ancora meglio usare i parametri per un motivo diverso: le prestazioni. Quando si separano i parametri dalla query, è possibile che si invii più volte lo stesso codice di query con parametri diversi. In tal caso, il database può memorizzare gran parte del lavoro svolto nella computazione della query, in modo che l'accesso al DB diventi più veloce. Ciò non funziona (o almeno non altrettanto bene) quando si mescolano i parametri nel codice di query stesso.

+6

+1 per il commento sulla "cache", molti SQL Server possono riutilizzare il piano di esecuzione dei suffissi sql. – RRUZ

+3

Probabilmente sarebbe insicuro in MySQL perché MySQL consente di evitare una citazione in modo che QuotedStr non aiuti qui. – Linas

+0

@Linas: buon punto. Modificato per tenerne conto. –

5

Ogni volta che si costruisce una stringa SQL concatenando stringhe, esiste la possibilità di un attacco di iniezione, non importa quanto sicuro si pensa accesso a tali stringhe sono. Per quanto ne sappia, qualcuno potrebbe eseguire la tua app all'interno di un debugger, inserire un breakpoint sul risultato di QuotedStr() e modificarne il contenuto prima di consentire a Format() di vederlo.

Uso dei parametri SQL reale è il modo più sicuro per andare. Non solo evita le iniezioni, ma consente anche al motore SQL di decidere il modo migliore per formattare i parametri in base alle proprie esigenze, quindi non devi preoccuparti di formattare i valori nel tuo codice, funziona bene con caratteri fortemente tipizzati lingue (come Delphi). Per non parlare dei vantaggi in termini di prestazioni derivanti dalla possibilità di preparare in anticipo l'istruzione SQL sul server prima di eseguirla nel codice, anche più volte, riducendo drasticamente il traffico tra client e server e aumentando le prestazioni complessive.

var 
    sCustomer : string 
begin 
    AdoSql.CommandText := 'Select SUM(value) result from invoices where customer=:Customer'; 
    AdoSql.Prepared := True; 
    ... 
    AdoSql.Parameters['Customer'].Value := sCustomer; 
    AdoSql1.ExecSQL; 
    ... 
    AdoSql.Parameters['Customer'].Value := sCustomer; 
    AdoSql1.ExecSQL; 
    ... 
    AdoSql.Prepared := False; 
end; 
+3

Questo primo paragrafo è un po 'sciocco. L'iniezione SQL è fondamentalmente basata sull'accesso non autorizzato al database. Ma se qualcuno ha accesso a livello di debug all'app stessa, non * necessita * di un attacco di SQL injection per ottenere l'accesso al database; si può presumere che abbiano già accesso ad esso, allo stesso livello di privilegio dell'app stessa. –

+1

Non se l'applicazione utilizza una connessione crittografata al database o se l'utente malintenzionato non può o non desidera determinare quale tipo di database viene utilizzato o come accedervi direttamente. Lascia che l'app faccia tutto il lavoro, basta cambiare l'SQL che viene eseguito. –

+2

In questo scenario, quindi l'utilizzo dei parametri sarebbe anche insicuro in quanto l'utente potrebbe modificare i valori dei parametri, cosa che a volte faccio quando eseguo il debug delle mie app. –

5

No, Format non offre sicurezza dall'iniezione SQL. Non è diverso dalla normale concatenazione di stringhe a tale riguardo.

La parte del codice nella domanda che fa qualcosa contro l'iniezione SQL è la chiamata a QuotedStr, che è possibile utilizzare con o senza Format. Non è affidabile come le query parametriche reali, però.

L'unico vantaggio di Format in questo contesto è che l'intero modello di corda è in un unico luogo, in modo da siete meno probabilità di ottenere la spaziatura e la punteggiatura sbagliata di quello che sarebbe se si dovesse costruire la stringa con successive operazioni + , dove gli apostrofi di SQL potrebbero perdersi tra gli apostrofi di Delphi.