it-swarm.com.de

Kann ich mich vor SQL-Injection schützen, indem ich einfache Anführungszeichen und umgebende Benutzereingaben mit einfachen Anführungszeichen verliere?

Mir ist klar, dass parametrisierte SQL-Abfragen die optimale Möglichkeit sind, Benutzereingaben zu bereinigen, wenn Abfragen erstellt werden, die Benutzereingaben enthalten. Ich frage mich jedoch, was falsch ist, wenn Benutzereingaben übernommen und einzelne Anführungszeichen ausgeblendet werden und die gesamte Zeichenfolge in einfache Anführungszeichen gesetzt wird. Hier ist der Code:

sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"

Alle einfachen Anführungszeichen, die der Benutzer eingibt, werden durch doppelte einfache Anführungszeichen ersetzt, wodurch der Benutzer nicht mehr in der Lage ist, die Zeichenfolge zu beenden. Daher sind alle anderen Eingaben wie Semikolons, Prozentzeichen usw. Teil der Zeichenfolge und Wird nicht als Teil des Befehls ausgeführt.

Wir verwenden Microsoft SQL Server 2000, für das meines Erachtens das einfache Anführungszeichen das einzige Zeichenfolgentrennzeichen und der einzige Weg ist, um das Zeichenfolgentrennzeichen zu umgehen. Es gibt also keine Möglichkeit, etwas auszuführen, das der Benutzer eingibt.

Ich sehe keine Möglichkeit, eine SQL-Injection-Attacke dagegen zu starten, aber mir ist klar, dass, wenn dies so kugelsicher wäre, wie es mir scheint, jemand anderes bereits darüber nachgedacht hätte und es übliche Praxis wäre.

Was ist los mit diesem Code? Gibt es eine Möglichkeit, einen SQL-Injection-Angriff über diese Desinfektionstechnik hinaus zu erhalten? Beispiel-Benutzereingaben, die diese Technik ausnutzen, wären sehr hilfreich.


AKTUALISIEREN:

Ich kenne immer noch keine Möglichkeit, einen SQL-Injection-Angriff gegen diesen Code zu starten. Ein paar Leute schlugen vor, dass ein Backslash ein einfaches Anführungszeichen überlässt und das andere die Zeichenfolge beendet, sodass der Rest der Zeichenfolge als Teil des SQL-Befehls ausgeführt wird eine MySQL-Datenbank, aber in SQL Server 2000 besteht die einzige Möglichkeit (die ich gefunden habe), ein einfaches Anführungszeichen zu umgehen, in einem anderen einfachen Anführungszeichen. Backslashes machen das nicht.

Und wenn es keine Möglichkeit gibt, das Entweichen des einfachen Anführungszeichens zu stoppen, wird keine der übrigen Benutzereingaben ausgeführt, da alle als eine zusammenhängende Zeichenfolge verwendet werden.

Ich verstehe, dass es bessere Möglichkeiten gibt, Eingaben zu bereinigen, aber ich bin mehr daran interessiert zu erfahren, warum die oben angegebene Methode nicht funktioniert. Wenn jemand eine bestimmte Möglichkeit kennt, einen SQL-Injection-Angriff gegen diese Desinfektionsmethode zu starten, würde ich sie gerne sehen.

129
Patrick

Zuallererst ist es nur schlechtes Training. Eingabevalidierung ist immer notwendig, aber es ist auch immer fraglich.
Schlimmer noch, die Validierung von Blacklists ist immer problematisch. Es ist viel besser, explizit und streng zu definieren, welche Werte/Formate Sie akzeptieren. Das ist zwar nicht immer möglich - muss aber zum Teil immer gemacht werden.
Einige Forschungsarbeiten zum Thema:

Der Punkt ist, dass jede von Ihnen erstellte Blacklist (und allzu zulässige Whitelists) umgangen werden kann. Der letzte Link zu meinem Artikel zeigt Situationen, in denen sogar das Entweichen von Anführungszeichen umgangen werden kann.

Auch wenn diese Situationen für Sie nicht zutreffen, ist es immer noch eine schlechte Idee. Darüber hinaus müssen Sie sich, sofern Ihre App nicht sehr klein ist, mit der Wartung und möglicherweise einer gewissen Governance befassen: Wie stellen Sie sicher, dass sie überall und jederzeit korrekt ausgeführt wird?

Der richtige Weg, es zu tun:

  • Whitelist-Validierung: Typ, Länge, Format oder akzeptierte Werte
  • Wenn Sie eine schwarze Liste erstellen möchten, fahren Sie fort. Das Entgehen von Zitaten ist gut, aber im Kontext der anderen Abschwächungen.
  • Verwenden Sie Befehls- und Parameterobjekte zum Vorbereiten und Überprüfen
  • Rufen Sie nur parametrisierte Abfragen auf.
  • Besser noch, verwenden Sie ausschließlich gespeicherte Prozeduren.
  • Vermeiden Sie die Verwendung von dynamischem SQL und verwenden Sie keine Zeichenfolgenverkettung, um Abfragen zu erstellen.
  • Wenn Sie SPs verwenden, können Sie die Berechtigungen in der Datenbank auch darauf beschränken, nur die erforderlichen SPs auszuführen und nicht direkt auf Tabellen zuzugreifen.
  • sie können auch leicht überprüfen, ob die gesamte Codebasis nur über SPs auf die DB zugreift ...
84
AviD

Okay, diese Antwort bezieht sich auf das Update der Frage:

"Wenn jemand eine bestimmte Möglichkeit kennt, einen SQL-Injection-Angriff gegen diese Desinfektionsmethode zu starten, würde ich das gerne sehen."

Jetzt gibt es neben dem MySQL-Backslash - und wenn man berücksichtigt, dass es sich tatsächlich um MSSQL handelt - tatsächlich drei Möglichkeiten, wie Sie Ihren Code mit Still SQL einfügen können

sSanitizedInput = "'" & Replace (sInput, "'", "''") & "'"

Bedenken Sie, dass diese nicht immer gültig sind und stark von Ihrem tatsächlichen Code abhängen:

  1. SQL-Injection zweiter Ordnung - Wenn eine SQL-Abfrage basierend auf Daten, die aus der Datenbank abgerufen wurden, neu erstellt wird nach dem Escape-Vorgang, werden die Daten unvermittelt verkettet und können indirekt SQL-Injected sein. Sehen
  2. Kürzung von Zeichenfolgen - (etwas komplizierter) - In diesem Fall haben Sie zwei Felder, z. B. einen Benutzernamen und ein Kennwort, und SQL verkettet beide. Und beide Felder (oder nur das erste) haben eine harte Längenbeschränkung. Beispielsweise ist der Benutzername auf 20 Zeichen begrenzt. Angenommen, Sie haben diesen Code:
username = left(Replace(sInput, "'", "''"), 20)

Dann erhalten Sie den Benutzernamen, der mit einem Escapezeichen versehen und dann auf 20 Zeichen gekürzt wurde. Das Problem hier - Ich werde mein Zitat in das 20. Zeichen einfügen (z. B. nach 19 Jahren), und Ihr Escaping-Zitat wird abgeschnitten (im 21. Zeichen). Dann die SQL

sSQL = "select * from USERS where username = '" + username + "'  and password = '" + password + "'"

in Kombination mit dem oben genannten ungültigen Benutzernamen ergibt sich, dass das Passwort bereits außerhalb in Anführungszeichen steht und nur die Nutzdaten direkt enthält.
3. Unicode-Schmuggel - In bestimmten Situationen ist es möglich, ein Unicode-Zeichen auf hoher Ebene zu übergeben, das sieht aus wie ein Zitat, aber ist nicht - bis es eintrifft in die Datenbank, wo plötzlich es ist. Da es sich bei der Validierung nicht um ein Zitat handelt, wird es einfach durchlaufen ... Weitere Details finden Sie in meiner vorherigen Antwort.

39
AviD

Kurz und bündig: Fragen Sie niemals selbst ab. Du wirst bestimmt etwas falsch machen. Verwenden Sie stattdessen parametrisierte Abfragen. Wenn Sie dies aus irgendeinem Grund nicht tun können, verwenden Sie eine vorhandene Bibliothek, die dies für Sie erledigt. Es gibt keinen Grund, es selbst zu tun.

27
Nick Johnson

Mir ist klar, dass dies eine lange Zeit ist, nachdem die Frage gestellt wurde, aber ..

Eine Möglichkeit, einen Angriff auf die 'quote the argument'-Prozedur zu starten, ist das Abschneiden von Zeichenfolgen. Laut MSDN wird in SQL Server 2000 SP4 (und SQL Server 2005 SP1) eine zu lange Zeichenfolge im Hintergrund abgeschnitten.

Wenn Sie eine Zeichenfolge zitieren, wird die Zeichenfolge größer. Jeder Apostroph wird wiederholt. Dies kann dann verwendet werden, um Teile der SQL außerhalb des Puffers zu verschieben. So können Sie Teile einer where-Klausel effektiv entfernen.

Dies ist wahrscheinlich vor allem in einem Szenario mit einer Seite für Benutzeradministratoren hilfreich, in dem Sie die Anweisung 'update' missbrauchen könnten, um nicht alle Überprüfungen durchzuführen, die sie durchführen sollten.

Wenn Sie sich also dazu entschließen, alle Argumente in Anführungszeichen zu setzen, vergewissern Sie sich, dass Sie wissen, was mit den Zeichenfolgengrößen geschieht, und stellen Sie sicher, dass Sie nicht auf Kürzungen stoßen.

Ich würde empfehlen, mit Parametern zu gehen. Immer. Ich wünschte nur, ich könnte das in der Datenbank durchsetzen. Als Nebeneffekt erhalten Sie mit größerer Wahrscheinlichkeit bessere Cache-Treffer, da mehr Anweisungen gleich aussehen. (Dies war sicherlich wahr auf Oracle 8)

17
Jørn Jensen

Input Hygiene ist nicht etwas, das Sie halbherzig machen wollen. Benutz deinen ganzen Arsch. Verwenden Sie reguläre Ausdrücke in Textfeldern. Versuchen Sie, Ihre Zahlen in den richtigen numerischen Typ umzuwandeln, und melden Sie einen Validierungsfehler, wenn er nicht funktioniert. Es ist sehr einfach, in Ihren Eingaben nach Angriffsmustern zu suchen, z. B. nach '-. Angenommen, alle Eingaben des Benutzers sind feindselig.

8
tom.dietrich

Ich habe diese Technik beim Umgang mit erweiterten Suchfunktionen verwendet, bei denen das Erstellen einer Abfrage von Grund auf die einzig gangbare Antwort war. (Beispiel: Ermöglichen Sie dem Benutzer die Suche nach Produkten basierend auf einer unbegrenzten Anzahl von Einschränkungen für Produktattribute, wobei Spalten und deren zulässige Werte als GUI-Steuerelemente angezeigt werden, um den Lernschwellenwert für Benutzer zu verringern.)

An sich ist es sicher AFAIK. Wie ein anderer Antwortender jedoch ausführte, müssen Sie möglicherweise auch mit dem Entweichen von Leerzeichen umgehen (wenngleich dies nicht der Fall ist, wenn Sie die Abfrage mit ADO oder ADO.NET) an SQL Server übergeben, kann dies zumindest nicht für alle Datenbanken oder Technologien).

Der Haken ist, dass Sie wirklich sicher sein müssen, welche Zeichenfolgen Benutzereingaben enthalten (immer potenziell böswillig) und welche Zeichenfolgen gültige SQL-Abfragen sind. Eine der Traps ist, wenn Sie Werte aus der Datenbank verwenden - wurden diese Werte ursprünglich vom Benutzer bereitgestellt? Wenn ja, müssen sie auch entkommen. Meine Antwort ist, zu versuchen, so spät wie möglich (aber nicht später!) Zu bereinigen, wenn die SQL-Abfrage erstellt wird.

In den meisten Fällen ist die Parameterbindung jedoch der richtige Weg - sie ist nur einfacher.

8
Pontus Gagge

Es ist sowieso eine schlechte Idee, wie Sie zu wissen scheinen.

Was ist mit so etwas wie dem Entgehen des Zitats in einer Zeichenfolge wie dieser:\'

Ihr Ersatz würde ergeben:\''

Wenn der Backslash vor dem ersten Anführungszeichen steht, hat das zweite Anführungszeichen die Zeichenfolge beendet.

6
WW.

Es gibt zwei Möglichkeiten, dies ohne Ausnahmen zu tun, um vor SQL-Injection sicher zu sein. vorbereitete Anweisungen und parametrisierte gespeicherte Prozeduren.

5
olle

Einfache Antwort: Es wird manchmal funktionieren, aber nicht die ganze Zeit. Sie möchten bei allem, was Sie tun , die Gültigkeitsprüfung auf der weißen Liste anwenden, aber mir ist klar, dass dies nicht immer möglich ist schwarze Liste. Ebenso möchten Sie parametrisierte gespeicherte Prozeduren in allem verwenden, aber auch dies ist nicht immer möglich, so dass Sie gezwungen sind, sp_execute mit Parametern zu verwenden.

Es gibt verschiedene Möglichkeiten, um eine verwendbare Blacklist zu umgehen (und auch einige Whitelists).

Eine anständige Beschreibung finden Sie hier: http://www.owasp.org/index.php/Top_10_2007-A2

Wenn Sie dies als schnelle Lösung benötigen, damit Sie Zeit haben, eine echte Lösung zu finden, sollten Sie dies tun. Aber denk nicht, dass du in Sicherheit bist.

5

Ihre Verteidigung würde scheitern, wenn:

  • die Abfrage erwartet eher eine Zahl als eine Zeichenfolge
  • es gab andere Möglichkeiten, ein einfaches Anführungszeichen darzustellen, einschließlich:
    • eine Escape-Sequenz wie\039
    • ein Unicode-Zeichen

(Im letzteren Fall müsste es sich um etwas handeln, das erst nach dem Ersetzen erweitert wurde.)

4
AJ.

Ja, das sollte funktionieren, bis jemand ausgeführt wird SET QUOTED_IDENTIFIER OFF und ein doppeltes Anführungszeichen für Sie verwendet.

Bearbeiten: Es ist nicht so einfach, dem böswilligen Benutzer das Deaktivieren von Bezeichnern in Anführungszeichen zu untersagen:

Der SQL Server Native Client ODBC Treiber und der SQL Server Native Client OLE DB Provider für SQL Server setzen QUOTED_IDENTIFIER automatisch auf ON, wenn eine Verbindung hergestellt wird. Dies kann in = konfiguriert werden ODBC Datenquellen, in ODBC Verbindungsattributen, oder OLE DB Verbindungseigenschaften. Die Standardeinstellung für SET QUOTED_IDENTIFIER ist OFF für Verbindungen von DB-Library-Anwendungen.

Wenn eine gespeicherte Prozedur erstellt wird, wird die Die Einstellungen SET QUOTED_IDENTIFIER und SET ANSI_NULLS werden erfasst und für nachfolgende Aufrufe dieser gespeicherten Prozedur verwendet.

SET QUOTED_IDENTIFIER auch entspricht der Einstellung QUOTED_IDENTIFER von ALTER DATABASE.

SET QUOTED_IDENTIFIER ist zur Analysezeit setzen. Das Setzen zur Analysezeit bedeutet, dass die SET-Anweisung, wenn sie im Stapel oder in der gespeicherten Prozedur vorhanden ist, wirksam wird, unabhängig davon, ob die Codeausführung tatsächlich diesen Punkt erreicht. und die SET-Anweisung wird wirksam, bevor Anweisungen ausgeführt werden.

Es gibt viele Möglichkeiten, wie QUOTED_IDENTIFIER ausgeschaltet sein kann, ohne dass Sie es unbedingt wissen. Zugegeben - das ist nicht der Raucher-Exploit, den Sie suchen, aber es ist eine ziemlich große Angriffsfläche. Natürlich, wenn Sie auch doppelte Anführungszeichen vermeiden - dann sind wir wieder da, wo wir angefangen haben. ;)

4
Mark Brackett

Patrick, setzen Sie ALLE Eingaben in einfache Anführungszeichen, auch Zahleneingaben? Wenn Sie eine numerische Eingabe haben, aber keine einfachen Anführungszeichen setzen, liegt eine Belichtung vor.

4
Rob Kraft

Wenn Sie parametrisierte Abfragen zur Verfügung haben, sollten Sie diese jederzeit verwenden. Es ist nur eine Abfrage erforderlich, um durch das Netz zu rutschen, und Ihre DB ist gefährdet.

4
Kev

Was für ein hässlicher Code wäre das für eine Bereinigung der Benutzereingaben! Dann der klobige StringBuilder für die SQL-Anweisung. Die vorbereitete Anweisungsmethode führt zu viel saubererem Code, und die SQL Injection-Vorteile sind eine wirklich nette Ergänzung.

Auch warum das Rad neu erfinden?

1
JeeBee

Anstatt ein einfaches Anführungszeichen in (wie es aussieht) zwei einfache Anführungszeichen zu ändern, können Sie es einfach in ein Apostroph oder ein Zitat ändern oder ganz entfernen.

So oder so, es ist ein bisschen kludge ... vor allem, wenn Sie legitim Dinge (wie Namen) haben, die einfache Anführungszeichen verwenden können ...

HINWEIS: Bei Ihrer Methode wird außerdem davon ausgegangen, dass sich jeder, der an Ihrer App arbeitet, immer daran erinnert, Eingaben zu bereinigen, bevor sie in die Datenbank gelangen. Dies ist wahrscheinlich die meiste Zeit nicht realistisch.

1
Kevin Fairchild

Es könnte funktionieren, aber es scheint mir ein wenig hokey. Ich würde empfehlen, die Gültigkeit jeder Zeichenfolge anhand eines regulären Ausdrucks zu überprüfen.

0
Rob

Während Sie möglicherweise eine Lösung finden, die für Zeichenfolgen funktioniert, müssen Sie für numerische Prädikate auch sicherstellen, dass sie nur Zahlen übergeben (einfache Prüfung: Kann diese als int/double/decimal analysiert werden?).

Es ist viel zusätzliche Arbeit.

0
Joseph Daigle