Ist die Abhängigkeit von parametrisierten Abfragen die einzige Möglichkeit, sich vor SQL-Injection zu schützen?

13

Alles, was ich bei SQL-Injection-Angriffen gesehen habe, scheint darauf hinzudeuten, dass parametrisierte Abfragen, insbesondere in gespeicherten Prozeduren, der einzige Weg sind, um sich vor solchen Angriffen zu schützen. Während meiner Arbeit (im dunklen Zeitalter) galten gespeicherte Prozeduren als schlechte Praxis, hauptsächlich weil sie als weniger wartbar angesehen wurden. weniger testbar; stark gekoppelt; und sperrte ein System in einen Lieferanten; ( Diese Frage deckt einige andere Gründe ab).

Während meiner Arbeit waren sich die Projekte der Möglichkeit solcher Angriffe praktisch nicht bewusst. Es wurden verschiedene Regeln verabschiedet, um die Datenbank gegen Korruption verschiedener Art zu sichern. Diese Regeln können wie folgt zusammengefasst werden:

  1. Kein Client / keine Anwendung hatte direkten Zugriff auf die Datenbanktabellen.
  2. Alle Zugriffe auf alle Tabellen erfolgten über Ansichten (und alle Aktualisierungen der Basistabellen erfolgten über Trigger).
  3. Für alle Datenelemente wurde eine Domäne angegeben.
  4. Kein Datenelement durfte nullwertfähig sein - dies hatte Auswirkungen darauf, dass die DBAs gelegentlich die Zähne knirschten. wurde aber durchgesetzt.
  5. Rollen und Berechtigungen wurden entsprechend eingerichtet - beispielsweise eine eingeschränkte Rolle, um nur Ansichten das Recht zu geben, die Daten zu ändern.

Ist eine Reihe von (erzwungenen) Regeln wie diese (wenn auch nicht unbedingt diese) eine geeignete Alternative zu parametrisierten Abfragen, um SQL-Injection-Angriffe zu verhindern? Wenn nein, warum nicht? Kann eine Datenbank durch (nur) datenbankspezifische Maßnahmen gegen solche Angriffe gesichert werden?

BEARBEITEN

Der Schwerpunkt der Frage hat sich im Lichte der eingegangenen ersten Antworten geringfügig geändert. Grundfrage unverändert.

EDIT2

Der Ansatz, sich auf parametrisierte Abfragen zu verlassen, scheint nur ein Randschritt bei der Abwehr von Angriffen auf Systeme zu sein. Es scheint mir, dass grundlegendere Abwehrmaßnahmen wünschenswert sind und das Verlassen auf solche Abfragen möglicherweise nicht erforderlich oder weniger kritisch erscheinen lassen, selbst wenn sie speziell gegen Injektionsangriffe verteidigt werden sollen.

Der in meiner Frage implizierte Ansatz beruhte auf der "Panzerung" der Datenbank, und ich hatte keine Ahnung, ob dies eine praktikable Option war. Weitere Untersuchungen haben ergeben, dass es solche Ansätze gibt. Ich habe die folgenden Quellen gefunden, die einige Hinweise auf diese Art von Ansatz geben:

http://database-programmer.blogspot.com

http://thehelsinkideclaration.blogspot.com

Die Hauptmerkmale, die ich diesen Quellen entnommen habe, sind:

  1. Ein umfangreiches Datenwörterbuch, kombiniert mit einem umfangreichen Sicherheitsdatenwörterbuch
  2. Generierung von Triggern, Abfragen und Constraints aus dem Data Dictionary
  3. Code minimieren und Daten maximieren

Während die Antworten, die ich bisher hatte, sehr nützlich sind und auf Schwierigkeiten hinweisen, die sich aus der Nichtbeachtung parametrisierter Abfragen ergeben, beantworten sie letztendlich nicht meine ursprünglichen Fragen (die jetzt fett hervorgehoben sind).

Chris Walton
quelle
Ich kaufe die Argumente nicht gegen gespeicherte Prozeduren. Sie sind einfach nicht wahr.
Konrad Rudolph
Was ist los mit der No-Nulls-Anforderung?
Mark Canlas
2
@Konrad Rudolph - Wenn Sie Ihre Anwendung auf MySQL schreiben und sich dann für eine Migration auf DB2 entscheiden, sind die gespeicherten Prozeduren Ihrer Meinung nach wirklich kompatibel? Ebenso, wenn Sie nach SQLLite migrieren möchten? Nehmen Sie außerdem an, Sie aktualisieren Ihr Betriebssystem. Wenn Ihre gespeicherten Prozeduren in C kompiliert werden (und sich in DB2 befinden), müssen sie wahrscheinlich alle neu kompiliert werden. Dies sind vernünftige Argumente - nicht absolut, aber vernünftig.
Matthew Flynn
@ Matthew Duh. Eigentlich dachte ich beim Lesen und Kommentieren an "parametrisierte Abfragen". Gespeicherte Prozedur = ganze Geschichte.
Konrad Rudolph

Antworten:

25

Gespeicherte Procs schützen nicht automatisch vor Injektionen. Was ist damit?

CREATE PROC proc
  @id VARCHAR(5)
AS
BEGIN
  EXEC("SELECT * FROM Client WHERE ClientId = " + @id);
END

Durch die Verwendung parametrisierter Abfragen werden Sie vor Injection geschützt, unabhängig davon, ob es sich um Procs handelt oder nicht.

Craig
quelle
Vielen Dank, dass Sie sich auf parametrisierte Abfragen und nicht auf procs konzentrieren. Ich frage mich jedoch, ob die Datenbank durch andere Methoden als solche Abfragen geschützt werden kann - insbesondere durch Methoden, die nur auf die Datenbankebene beschränkt sind.
Chris Walton
1
+1 Darüber hinaus möchte ich darauf hinweisen, dass gespeicherte Prozesse meistens als sicher angesehen werden, da dies die einzige Möglichkeit ist, Benutzer daran zu hindern, direkt auf Tabellen zuzugreifen, während die Möglichkeit zum Abrufen der Daten beibehalten wird. Dies ist die einzige Möglichkeit, zeilenbasierte und spaltenbasierte Berechtigungen zu gewährleisten, wenn der Benutzer direkten Datenbankzugriff mit seinem Client benötigt, ohne dass etwas dazwischen liegt.
Falcon
2
@ Chris - Ich denke, was Craig hier sagt, ist, dass Sie nicht davon ausgehen können, dass Procs Sie tatsächlich schützen. Es ist vielleicht keine vollständige Antwort, eher eine Korrektur der Annahme im Titel.
Jon Hopkins
@ Jon - Ich habe den Titel der Frage geändert und einige Änderungen an der Frage vorgenommen, im Lichte von Craigs Korrektur. Ich war mir der Annahme, die ich in der Frage machte, nicht bewusst, bis ich anfing, Antworten zu erhalten.
Chris Walton
2
Weitere Informationen zu Craig finden Sie unter databasesecurity.com/dbsec/lateral-sql-injection.pdf , "Lateral SQL Injection: Eine neue Klasse von Sicherheitslücken in Oracle"
Bruce Ediger
11

Ist eine Reihe von (erzwungenen) Regeln wie diese eine geeignete Alternative zu gespeicherten Prozeduren, um SQL-Injection-Angriffe zu verhindern? Wenn nein, warum nicht?

Nein, weil sie den Entwicklern eine schwere Strafe auferlegen. Eine Aufschlüsselung nach Artikeln:

1. Kein Client / keine Anwendung hatte direkten Zugriff auf die Datenbanktabellen.

Verwenden Sie Rollen. Clients sollten nur über eine eingeschränkte Rolle auf die Datenbank zugreifen können, die nur über SELECT-, INSERT-, UPDATE- und DELETE-Zugriff auf die Tabellen (und Zeilen, sofern möglich) verfügt, auf die sie Zugriff benötigen. Wenn Sie sicherstellen möchten, dass kein Client alle Einträge als Spam versenden oder löschen kann, verwenden Sie eine API zur Datenänderung.

2. Alle Zugriffe auf alle Tabellen erfolgten über Ansichten.

Dies kann je nach Effizienz der Ansichten von vernachlässigbar bis zu enormen Leistungskosten führen. Es ist unnötige Komplexität, die die Entwicklung verlangsamt. Verwenden Sie Rollen.

3. Für alle Datenelemente wurde eine Domäne angegeben.

Könnte eine Menge Arbeit bedeuten und sollte wahrscheinlich in eine separate Tabelle normalisiert werden.

4. Kein Datenelement durfte nullwertfähig sein - dies hatte Auswirkungen darauf, dass die DBAs gelegentlich die Zähne knirschten. wurde aber durchgesetzt.

Das ist einfach falsch. Wenn die Entwickler nicht in der Lage sind, mit NULLs umzugehen, haben Sie große Probleme.

Kann eine Datenbank durch (nur) datenbankspezifische Maßnahmen gegen solche Angriffe gesichert werden?

Sie benötigen keine gespeicherten Prozeduren, sondern verwenden nur parametrisierte Abfragen mit einer Funktion, die sich den Argumenten entzieht, wie z. B. pg_query_params . Natürlich, wenn Ihre Datenbank von der Welt beschreibbar ist oder die Client-Rolle vollen Zugriff auf alles hat, sind Sie sowieso beschissen. Jemand muss einfach mitkommen und erkennen, was der Kunde tut, und dann in fünf Minuten einen Kunden ausheizen, der Ihre Datenbank zerstört (oder schlimmer noch, vergiftet).

l0b0
quelle
1
Domain: en.wikipedia.org/wiki/Data_domain
Dan McGrath
+1 für Rollen. Sie tragen wesentlich dazu bei - ich habe keine Rollen in meine Frage aufgenommen, aber sie waren Teil des Setups -, insbesondere wurde den Ansichten eine eingeschränkte Rolle zugewiesen, wie Sie sie für Kunden vorschlagen. Punkt genommen auf dem Leistungstreffer der Ansichten. Domänen enthalten Validierungstests - Bereiche und Länge meist. Ihre Kommentare zur Daten-NULL-Regel sind viel höflicher als einige, die ich über diese Regel gehört habe. Ich habe nicht ausdrücklich angegeben, dass die Berechtigungen ordnungsgemäß eingerichtet werden, obwohl dies meine Annahme war.
Chris Walton
6

Ich bin mir nicht sicher, ob deine Regeln dich vollständig schützen.

Das erste Problem ist, dass Sie angeben, dass sie durchgesetzt werden, aber ich habe nie eine perfekte Durchsetzung gesehen, obwohl sie einen erheblichen Mehraufwand mit sich bringt.

Zweitens ist meine Lektüre, dass Regeln wie diese die Ausnutzung der Dinge erschweren, aber sie verhindern es nicht. Wenn Sie beispielsweise keinen direkten Zugriff auf die Tabellen haben, ändert sich nicht viel, wenn Sie in den Ansichten auf dieselben Daten zugreifen können. Wenn der Client etwas tun muss, muss eine Ansicht dies ermöglichen, und wenn eine Ansicht dies ermöglicht, kann ein Angreifer dieselben Funktionen / Daten verwenden.

Denken Sie auch daran, dass es nicht nur um das Aktualisieren oder Löschen von Daten geht. Ein Teil der Sicherheitsanfälligkeit bei SQL Injection ist das Sammeln von Informationen. Dabei ist es Ihnen egal, ob die Daten über die View vCustomers- oder die zugrunde liegende Customers-Tabelle zurückgegeben wurden. Sie haben sich vielleicht vor einigen Schwächen geschützt, aber nicht vor allen. In ähnlicher Weise kann SQL geschrieben werden, um die Trigger auszulösen und Aktualisierungen vorzunehmen, wenn die Aktualisierungen vom Client vorgenommen werden können, auch wenn sie durch Trigger ausgeführt werden.

(In Bezug auf alle Aktualisierungen, die über Trigger vorgenommen werden, möchte ich zwei Dinge sagen: (1) Als ich dies las, war ich ein bisschen krank im Mund und (b) Sie mögen gespeicherte Prozeduren nicht, weil sie Sie sind "weniger wartbar, weniger testbar, stark gekoppelt und haben ein System an einen einzigen Anbieter gebunden", aber Sie verwenden Trigger, über die im Grunde die gleichen Dinge gesagt werden können.)

Alles, was Sie brauchen, ist eine Lücke, die die Ausführung von SQL-Anweisungen ermöglicht (und ich sehe keine dieser Regeln, die dies verhindern), und der Angreifer ist dabei. Er findet möglicherweise eine sehr unintuitive Datenbank dahinter, aber wenn er dies bestimmt verlangsamen sie nur, anstatt sie zu stoppen).

Die andere Sache hier ist, dass Sie auch Komplexität hinzufügen und (ebenso wie der Aufwand, der entsteht), Komplexität dazu neigt, zu Lücken zu führen, die ausgenutzt werden können.

Ich sage nicht, dass ein solches Regelwerk nicht erstellt werden kann - mehr, warum sollten Sie sich die Mühe machen? Sie scheinen umständlicher und weniger zuverlässig zu sein, als nur mit den allgemein anerkannten Methoden zur Verhinderung solcher Angriffe umzugehen.

Jon Hopkins
quelle
+1, um meine eigentliche Anfrage im Lichte meiner impliziten, unbewussten Annahmen zu verstehen und angemessen darauf zu reagieren. Was den Grund angeht, warum man sich die Mühe machen könnte - ich arbeite an einem Projekt, bei dem ein Großteil des Codes aus einer relevanten Beschreibung der Architektur generiert wird - und ein Teil dieser Architektur beschreibt, wie Datenbankzugriffsroutinen generiert werden. Es ist noch offen, wie diese generierten Routinen aussehen werden.
Chris Walton