2012-11-01 15 views
7

Ich habe meinen ersten SQL-Escape-Fehler gebissen (es war lange überfällig), als ich versuchte, die PostgreSQL-Abfrage unten mit einem Wert auszuführen, der ein Apostroph enthielt, z. O'Brien, mit Freepascal und LazarusGibt es eine Bibliothek zum Säubern von Abfrageparametern für PostgreSQL oder SQL im Allgemeinen, für FreePascal und 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)])); 

In der Abfrage oben SQuote ist eine Funktion, die eine Zeichenfolge in einfachen Anführungszeichen umschließt. Gibt es eine Standardbibliothek zur Bereinigung von SQL-Abfrageparametern für Lazarus/FreePascal oder Delphi?

+0

Sie können "QuotedStr" -Funktion verwenden (versuchen, sql-injizieren, dass ...) – kobik

Antwort

16

Ihre Anwendung ist anfällig für eine schwerwiegende Klasse von Sicherheitsproblemen mit der Bezeichnung SQL injection. Siehe http://bobby-tables.com/.

Sicher, O'Brian verursacht einen Fehler, aber was ist mit ');DROP SCHEMA public;--? Oder ');DELETE FROM users;--? Der 1. sollte nicht funktionieren, weil Ihre App nie als Superuser oder der Benutzer ausführen sollte, der die Tabellen besitzt, aber wenige Anwendungsdesigner die Mühe machen, dies zu tun und oft privilegierte Benutzer in der Produktion ausführen. Das 2. wird in den meisten Anwendungen funktionieren; Details finden Sie am Ende des Posts.

Die einfachste und beste vorbeugende Maßnahme ist parametrisierte Anweisungen* in der Client-Bibliothek zu verwenden. Siehe this example für 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; 

(Ich habe Delphi nie benutzt und zuletzt schrieb Pascal-Code 1995; ich zitiere nur das Beispiel).

Was Sie gerade tun, ist String-Interpolation von Parametern. Es ist sehr gefährlich. Es kann nur sicher ausgeführt werden, wenn Sie eine robuste Funktion für haben, die SQL-Literale zitiert, eine, die nicht nur Anführungszeichen an jedem Ende knallt, sondern auch andere Escapezeichen, doppelte Anführungszeichen usw. behandelt. Es ist der Ansatz des letzten Ausweges; es ist stark bevorzugt, eine parametrisierte Anweisung zu verwenden.


Hier ist eine Erweiterung des oben angegebenen Beispiels. Angenommen, Sie einen ganz gewöhnlichen Einsatz eines Benutzers von Benutzernamen zu tun, wo ‚Fred‘ vom Client ein Beispiel Benutzername eingegeben wird:

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

Jetzt sind einige unangenehme Person ');DELETE FROM users;-- den Benutzernamen sendet. Plötzlich Ihre Anwendung ausgeführt wird:

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

die, wenn sie erweitert ist:

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

oder mit anderen Worten ein Einsatz, der eine leere Zeichenfolge einfügt (obwohl sie könnten genauso gut ein perfekt gültigen Benutzernamen in Put) , gefolgt von einer DELETE FROM users; Anweisung - Löschen aller Zeilen in users - dann ein Kommentar, der nichts tut. Splat. Da gehen deine Daten hin.


* Parameterized statemments werden manchmal falsch als vorbereitete Anweisungen bezeichnet.Das ist falsch, weil eine vorbereitete Anweisung nicht unbedingt parametrisiert ist und eine parametrisierte Anweisung nicht unbedingt vorbereitet ist. Die Verwirrung ist entstanden, weil die Datenbankschnittstellen vieler Sprachen keine Möglichkeit bieten, parametrisierte Anweisungen zu verwenden, ohne auch vorbereitete Anweisungen zu verwenden.

+2

Darüber hinaus existiert ein ähnliches Design von Bibliotheken für PHP (eine der ersten Schritte zu meistern) und alle anderen Web-Skriptsprachen. Es löst auch Probleme der String-Entweichen, unterschiedliche DATE-Darstellung und dergleichen. "Sanitizing" -Parameter sind Ad-hoc- "armer Mann" -Ersatz für klare Parametertrennung. Wenn Sie stattdessen jemandes Code mit "Bereinigung" sehen, dann hat er höchstwahrscheinlich entweder keine moderne Bibliothek bekommen oder einfach keine Sicherheit bekommen. –

+0

Ich habe diese Frage gestellt, weil ich weiß, dass dies ein Minenfeld ist, selbst für diejenigen, die denken, dass sie das Problem haben. Ich weiß über parametrisierte Abfragen Bescheid, möchte aber wissen, ob sie sicher sind, dass sie von einigen sachkundigeren Personen ebenfalls getäuscht werden können. – vfclists

+2

@vfclists Die korrekte Verwendung von parametrisierten Abfragen wird SQL-Injection-Angriffe * absolut verhindern, es sei denn, dass dynamisches SQL in der Datenbank * ausgeführt wird, z. B. durch eine PL/pgSQL 'EXECUTE'-Anweisung. Wenn Sie dynamisches SQL in der DB verwenden, müssen Sie auch dort vor SQL-Injection schützen, wobei Sie den Formatbezeichner '% I' der' format'-Funktion und 'EXECUTE ... USING' verwenden. Siehe diese vorherige Antwort für dieses Problem: http://stackoverflow.com/a/12995424/398670. –