2012-11-01 9 views
7

Sono stato morso il mio primo errore di escape sql (era in ritardo da tempo) quando ho provato ad eseguire la query PostgreSQL di seguito con un valore contenente un apostrofo es. O'Brien, utilizzando FreePascal e LazzaroEsiste una libreria per la sanificazione dei parametri di query per PostgreSQL o SQL in generale, per FreePascal e Delphi?

SQL.Add(format('select * from zones where upper(zn_name) >= %s and upper(zn_name) < %s order by zn_name',[sQuote(zoneMin), sQuote(zoneMax)])); 

Nella query sopra squote è una funzione che avvolge una stringa tra apici. C'è qualche libreria standard per sanificare i parametri di query SQL per Lazarus/FreePascal o Delphi?

+0

È possibile utilizzare la funzione 'QuotedStr' (provare a sql-iniettare che ...) – kobik

risposta

16

L'applicazione è vulnerabile a una seria classe di problemi di sicurezza denominata SQL injection. Vedi http://bobby-tables.com/.

Certo, O'Brian causa un errore, ma che dire di ');DROP SCHEMA public;--? O ');DELETE FROM users;--? Il primo non dovrebbe funzionare perché la tua app deve mai eseguita come superutente o utente che possiede le tabelle, ma pochi progettisti di applicazioni si sforzano di farlo realmente e spesso eseguono utenti privilegiati nella produzione. Il 2 funzionerà nella maggior parte delle applicazioni; vedere la fine del post per i dettagli.

La misura preventiva più semplice e migliore è quello di utilizzare dichiarazioni con parametri* nella tua libreria client. Vedere this example per Delpi:

To use a prepared statement, do something like this: 

query.SQL.Text := 'update people set name=:Name where id=:ID'; 
query.Prepare; 
query.ParamByName('Name').AsString := name; 
query.ParamByName('ID').AsInteger := id; 
query.ExecSQL; 

(non ho mai usato Delphi e ultimo scritto il codice Pascal nel 1995, sto solo citando l'esempio dato).

Quello che si sta facendo attualmente è interpolazione stringa di parametri. È molto pericoloso. Può essere fatto in sicurezza solo se si dispone di una funzione robusta per che cita letterali SQL, uno che non si limita a virgolette su ciascuna estremità, ma gestisce anche altre fughe, virgolette doppie, ecc. È l'approccio di ultima istanza; è fortemente preferibile utilizzare una dichiarazione parametrizzata.


Ecco un'espansione dell'esempio che ho dato sopra. Diciamo che si sta facendo un inserto perfettamente normale di un utente per nome utente, dove 'Fred' è un esempio di input nome utente da parte del cliente:

INSERT INTO users (user_name) VALUES ('Fred'); 

Ora qualche persona sgradevole invia il nome utente ');DELETE FROM users;--. Improvvisamente l'applicazione viene eseguita:

INSERT INTO users (user_name) VALUES ('');DELETE FROM users;--'); 

che quando espanso è:

INSERT INTO users (user_name) VALUES (''); 
DELETE FROM users; 
--'); 

o in altre parole un inserto che inserisce una stringa vuota (anche se potrebbe facilmente mettere un nome utente perfettamente valido) , seguito da una dichiarazione DELETE FROM users; - eliminazione di tutte le righe in users - quindi un commento che non fa nulla. Splat. Ecco i tuoi dati.


* statemments parametrizzati sono a volte indicato erroneamente come istruzioni preparate.Ciò non è corretto perché un'istruzione preparata non è necessariamente parametrizzata e un'istruzione parametrizzata non è necessariamente preparata. La confusione è sorta perché le interfacce database di molti linguaggi non forniscono un modo per utilizzare istruzioni parametrizzate senza utilizzare anche istruzioni preparate.

+2

Inoltre, esiste una progettazione simile di librerie per PHP (in base ai primi passi per la sua padronanza) e tutti gli altri linguaggi di scripting web. Risolve anche problemi di escape delle stringhe, diversa rappresentazione DATE e così via. I parametri "Sanitizing" sono sostituzioni ad hoc di "poor man" per una chiara separazione dei parametri. Se vedi il codice di qualcuno con "disinfettante" invece molto probabilmente non ha né la biblioteca moderna né la sicurezza. –

+0

Ho fatto questa domanda perché so che questo è un campo minato anche per coloro che pensano di avere il problema collegato. Conosco le query parametrizzate, ma voglio sapere se sono garantite per essere sicure, di alcune persone più informate possono ingannare anche loro. – vfclists

+2

@vfclists L'uso corretto delle query con parametri previene assolutamente gli attacchi di SQL injection * a meno che SQL dinamico non venga eseguito nel database *, ad esempio da un'istruzione 'EXECUTE' PL/pgSQL. Se stai utilizzando SQL dinamico nel DB devi proteggerti anche da SQL injection, con l'uso attento dello specificatore di formato '% I' della funzione' format' e con 'EXECUTE ... USING'. Vedi questa risposta precedente per quel problema: http://stackoverflow.com/a/12995424/398670. –

Problemi correlati