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

StackOverflow https://stackoverflow.com/questions/139199

Frage

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 daran ist, Benutzereingaben entgegenzunehmen, einfache Anführungszeichen zu maskieren und die gesamte Zeichenfolge in einfache Anführungszeichen zu setzen.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 die Möglichkeit hat, die Zeichenfolge zu beenden, sodass alles andere, was er möglicherweise eingibt, wie Semikolons, Prozentzeichen usw., Teil der Zeichenfolge ist und nicht tatsächlich als Teil des Befehls ausgeführt.Wir verwenden Microsoft SQL Server 2000, für das meiner Meinung nach das einfache Anführungszeichen das einzige Zeichenfolgentrennzeichen und die einzige Möglichkeit ist, das Zeichenfolgentrennzeichen zu umgehen, sodass es keine Möglichkeit gibt, etwas auszuführen, was der Benutzer eingibt.

Ich sehe keine Möglichkeit, dagegen einen SQL-Injection-Angriff 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 gängige Praxis wäre.Meine Frage ist diese:Was stimmt mit diesem Code nicht?Kennt jemand eine Möglichkeit, einen SQL-Injection-Angriff über diese Sanierungstechnik hinaus zu verhindern?Beispielbenutzereingaben, die diese Technik ausnutzen, wären sehr hilfreich.

AKTUALISIEREN:

Vielen Dank an alle für ihre Antworten;So ziemlich alle Informationen, die ich bei meinen Recherchen gefunden habe, sind irgendwo auf dieser Seite aufgetaucht, was ein Zeichen für die Intelligenz und das Können der Menschen ist, die sich in ihrem arbeitsreichen Tag die Zeit genommen haben, mir bei dieser Frage zu helfen.

Der Grund, warum ich noch keine der Antworten akzeptiert habe, ist, dass ich immer noch keine Möglichkeit kenne, effektiv einen SQL-Injection-Angriff gegen diesen Code zu starten.Einige Leute schlugen vor, dass ein Backslash einem einfachen Anführungszeichen entkommen und das andere am Ende der Zeichenfolge belassen würde, sodass der Rest der Zeichenfolge als Teil des SQL-Befehls ausgeführt würde, und mir ist klar, dass diese Methode funktionieren würde, um SQL einzufügen eine MySQL-Datenbank, aber in MS SQL 2000 ist die einzige Möglichkeit (die ich finden konnte), ein einfaches Anführungszeichen zu umgehen, ein anderes einfaches Anführungszeichen;Backslashes reichen nicht aus.Und es sei denn, es gibt eine Möglichkeit, das Escapezeichen des einfachen Anführungszeichens zu verhindern, wird der Rest der Benutzereingabe nicht ausgeführt, da alles als eine zusammenhängende Zeichenfolge betrachtet wird.

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

War es hilfreich?

Lösung

Zunächst einmal, es ist nur eine schlechte Praxis. Input-Validierung ist immer notwendig, aber es ist auch immer strittig.
Schlimmer noch, ist schwarze Liste Validierung immer problematisch, es viel besser ist und streng explizit definieren, welche Werte / Formate, die Sie akzeptieren. Zugegeben, dies ist nicht immer möglich - aber zu einem gewissen Grad muss es immer getan wird
. Einige Forschungsarbeiten zum Thema:

Punkt ist, jede schwarze Liste Sie tun (und auch permissive weiße Listen) kann umgangen werden. Der letzte Link zu meinem Beitrag zeigt Situationen, in denen sogar Zitat Entkommen umgangen werden kann.

Auch wenn diese Situationen Sie gelten nicht, es ist immer noch eine schlechte Idee. Darüber hinaus, es sei denn Ihre Anwendung trivialer klein ist, Sie gehen mit Wartung zu tun haben, und vielleicht auch ein gewisses Maß an Governance: Wie stellen Sie sicher, dass ihr es richtig gemacht, überall die ganze Zeit

Der richtige Weg, es zu tun:

  • Weiße Liste Validierung: Typ, Länge, Format oder akzeptiert Werte
  • Wenn Sie auf die schwarze Liste wollen, gehen Sie nach rechts weiter. Zitat Entkommen ist gut, aber im Zusammenhang mit den anderen mitigations.
  • Verwenden Sie Befehl und Parameter-Objekten, auf preparse und zu validieren
  • Rufen Sie nur parametrisierte Abfragen.
  • Noch besser wäre es, die Verwendung von gespeicherten Prozeduren ausschließlich.
  • Vermeiden Sie dynamische SQL verwenden und nicht String-Verkettung verwenden, um Abfragen zu erstellen.
  • Wenn SPs verwenden, können Sie auch Berechtigungen in der Datenbank zu begrenzen nur die benötigte SPs auf der Ausführung und Tabellen nicht direkt zugreifen.
  • Sie können auch leicht überprüfen, dass die gesamte Codebasis nur die DB durch SPs greift ...

Andere Tipps

Okay, diese Reaktion auf die Aktualisierung der Frage beziehen wird:

  

„Wenn jemand weiß, der eine bestimmte Art und Weise einen SQL-Injection-Angriff gegen diese sanitization Methode zu montieren ich lieben würde, es zu sehen.“

Nun, neben der MySQL-Backslash - und unter Berücksichtigung, dass wir reden eigentlich über MSSQL, gibt es tatsächlich drei Möglichkeiten, noch Ihren Code SQL Injektion

  

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

Beachten Sie, dass diese werden alle nicht gültig zu allen Zeiten, und sind sehr abhängig von Ihrem aktuellen Code um es:

  1. zweiter Ordnung SQL Injection - wenn eine SQL-Abfrage auf der Basis von Daten aus der Datenbank nach der Flucht abgerufen neu erstellt wird, werden die Daten verketteten unescaped und indirekt SQL-injiziert werden. Siehe
  2. String Abschneiden - (etwas komplizierter) - Szenario ist, dass Sie haben zwei Felder, sagen einen Benutzernamen und ein Passwort, und die SQL verkettet beide. Und beide Felder (oder nur die erste) eine harte Grenze auf Länge. Zum Beispiel ist der Benutzername auf 20 Zeichen begrenzt. Sagen Sie bitte diesen Code haben:
username = left(Replace(sInput, "'", "''"), 20)

Dann, was man bekommt - der Benutzername ist, entkam, und getrimmt dann zu 20 Zeichen. Das Problem hier - ich werde mein Zitat im 20. Charakter bleiben (zum Beispiel nach 19 a Jahren), und Ihre Flucht Zitat wird (im 21. Zeichen) getrimmt werden. Dann wird die SQL

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

mit dem oben genannten ungültigen Benutzernamen kombiniert führt in das Passwort bereits sein außerhalb die Anführungszeichen, und enthält nur die Nutzlast direkt.
 3. Unicode Schleusung - In bestimmten Situationen ist es möglich, eine High-Level-Unicode-Zeichen zu übergeben, die sieht wie ein Zitat, aber nicht - bis er die bekommt Datenbank, in der plötzlich ist es . Da es kein Zitat ist, wenn Sie es bestätigen, wird es durch einfache gehen ... Meine vorherige Antwort, um weitere Informationen und Link zur Original-Forschung.

Auf den Punkt gebracht: Nie Abfrage keine Flucht selbst. Sie sind verpflichtet, etwas falsch zu bekommen. Verwenden Sie stattdessen parametrisierte Abfragen, oder wenn Sie nicht aus irgendeinem Grund tun, eine vorhandene Bibliothek verwenden, die dies für Sie tut. Es gibt keinen Grund, es selbst zu tun.

Ich weiß, das ist eine lange Zeit, nachdem die Frage wurde gefragt, aber ..

Eine Möglichkeit, einen Angriff auf dem ‚zitiert das Argument‘ -Prozedur zu starten ist mit Zeichenfolge abgeschnitten. Laut MSDN, in SQL Server 2000 SP4 (und SQL Server 2005 SP1), wird eine zu lange Zeichenfolge ruhig abgeschnitten.

Wenn Sie zitieren eine Zeichenfolge, die Zeichenfolge in der Größe zunimmt. Jeder Apostroph wird wiederholt. Dies kann dann dazu verwendet werden, um Teile des SQL außerhalb des Puffers zu drücken. So können Sie effektiv Teile einer where-Klausel wegschneiden könnte.

Dies würde wahrscheinlich vor allem nützlich sein, in einem ‚Benutzer admin‘ Seite Szenario, in dem Sie die ‚update‘ Aussage missbrauchen könnten, um alle Kontrollen nicht tut es tun sollte.

Also, wenn Sie sich entscheiden, alle Argumente zu zitieren, stellen Sie sicher wissen, was mit den String-Größen geht weiter und dafür sorgen, dass Sie nicht in Verkürzungs laufen.

Ich würde empfehlen, mit den Parametern gehen. Immer. Ich wünschte nur, ich, dass in der Datenbank erzwingen könnte. Und als Nebeneffekt, sind Sie eher besser Cache-Hits zu bekommen, weil mehrere der Aussagen gleich aussehen. (Dies war sicherlich richtig auf Oracle 8)

Input Hygiene ist nicht etwas, das man auf die Hälfte-ass wollen. Verwenden Sie Ihre ganze ass. Verwenden Sie reguläre Ausdrücke auf Textfelder. TryCast Ihre Numerik an den richtigen numerischen Typ, und berichten über einen Validierungsfehler, wenn es nicht funktioniert. Es ist sehr einfach für Angriffsmuster in Ihrer Eingabe zu suchen, wie zum Beispiel '-. Angenommen, alle Eingaben vom Benutzer feindlich sind.

Ich habe diese Technik verwendet wird, wenn mit ‚erweiterte Suche‘ -Funktionalität zu tun, wo eine Abfrage von Grunde auf die einzige praktikable Antwort war zu bauen. (Beispiel:. Erlauben dem Benutzer, nach Produkten zu suchen, basierend auf einer unbegrenzten Menge von Einschränkungen auf die Produktattribute, Anzeige Spalten und ihre zulässigen Werte als GUI steuert die Lernschwelle für Anwender zu verringern)

An und für sich ist es sicher, AFAIK. Als eine andere Antworter wies jedoch darauf hin, dass Sie auch mit Backspace müssen umgehen zu entkommen (wenn auch nicht, wenn die Abfrage auf SQL Server vorbei ADO oder ADO.NET verwenden, zumindest - nicht für alle Datenbanken oder Technologien bürgen).

Der Haken ist, dass Sie wirklich sicher sein, haben die Strings von Benutzereingaben (immer potentiell schädliche) enthalten, und die Zeichenfolgen sind gültige SQL-Abfragen. Eine der Fallen ist, wenn Sie Werte aus der Datenbank verwenden - wurden diese Werte ursprünglich vom Benutzer gelieferten? Wenn ja, müssen sie auch entwertet werden. Meine Antwort ist, zu versuchen, so spät wie möglich (aber nicht später!) Zu sanieren, wenn die SQL-Abfrage zu konstruieren.

Doch in den meisten Fällen Parameterbindung ist der Weg zu gehen - es ist nur einfacher.

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

Was ist so etwas wie das Zitat in Zeichenfolge wie folgt zu entkommen: \ '

Ihr ersetzen würde in: \ ''

Wenn der Backslash das erste Zitat entkommt, dann das zweite Zitat die Zeichenfolge beendet ist.

Einfache Antwort: Es wird manchmal funktionieren, aber nicht die ganze Zeit. Sie wollen sich auf alles weiß-Liste Validierung verwenden Sie tun, aber ich merke, das ist nicht immer möglich, so dass Sie mit der besten Vermutung schwarze Liste zu gehen gezwungen sind. Ebenso wollen Sie parametrisierte gespeicherte Procs in alles , aber noch einmal verwenden, das ist nicht immer möglich, so dass Sie mit den Parametern zu verwenden Sp_execute gezwungen sind.

Es gibt Möglichkeiten, um jede verwendbare schwarze Liste Sie mit oben kommen können (und einige weißen Listen auch).

Ein ordentliches writeup ist hier: http://www.owasp.org/index. php / Top_10_2007-A2

Wenn Sie dies als eine schnelle Lösung tun, müssen Sie Zeit zu geben, eine echte an seinem Platz zu bekommen, tun Sie es. Aber denken Sie nicht, dass Sie sicher sind.

Es gibt zwei Möglichkeiten, es zu tun, keine Ausnahmen, zum Schutz vor SQL-Injektionen zu sein; Prepared Statements oder prameterized Stored Procedures.

Wenn Sie Fragen zur Verfügung parametriert haben, sollten Sie sie jederzeit benutzen. Alles was man braucht ist für eine Abfrage durch das Netz zu schlüpfen und Ihre DB ist in Gefahr.

Ja, das sollte funktionieren, bis jemand rennt SETZEN SIE QUOTED_IDENTIFIER AUS und verwendet ein doppeltes Anführungszeichen für Sie.

Bearbeiten:Es ist nicht so einfach, dem böswilligen Benutzer nicht zu erlauben, zitierte Bezeichner zu deaktivieren:

Der SQL Server Native Client ODBC-Treiber und der SQL Server Native Client OLE DB-Anbieter für SQL Server legen QUOTED_IDENTIFIER beim Herstellen der Verbindung automatisch auf ON fest.Dies kann in ODBC-Datenquellen, in ODBC-Verbindungsattributen oder OLE DB-Verbindungseigenschaften konfiguriert werden. Der Standardwert 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.

SETZEN Sie auch QUOTED_IDENTIFIER entspricht der QUOTED_IDENTIFER-Einstellung von ALTER DATABASE.

SET QUOTED_IDENTIFIER ist Wird zum Parse-Zeitpunkt festgelegt.Das Setzen zum Zeitpunkt der Analyse bedeutet, dass die SET-Anweisung wirksam wird, wenn sie im Batch oder in der gespeicherten Prozedur vorhanden ist, unabhängig davon, ob die Codeausführung diesen Punkt tatsächlich erreicht.und die SET-Anweisung wird wirksam, bevor Anweisungen ausgeführt werden.

Es gibt viele Möglichkeiten, wie QUOTED_IDENTIFIER falsch sein könnte, ohne dass Sie es unbedingt wissen.Zugegebenermaßen ist dies nicht der entscheidende Exploit, nach dem Sie suchen, aber es ist eine ziemlich große Angriffsfläche.Wenn Sie auch doppelte Anführungszeichen vermieden haben, sind wir natürlich wieder da, wo wir angefangen haben.;)

Ihre Verteidigung würde scheitern, wenn:

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

(im letzteren Fall wäre es etwas sein, die nur erweitert wurden, nachdem Sie getan haben Ihre ersetzen)

Patrick, fügen Sie einfache Anführungszeichen um alle Eingabe, auch numerische Eingabe? Wenn Sie numerische Eingabe haben, sind aber nicht die einzigen Anführungszeichen um es setzen, dann haben Sie eine Exposition.

Welche hässliche Code alles Hygienisierung von Benutzereingaben wäre! Dann wird die klobigen Stringbuilder für die SQL-Anweisung. Die vorbereitete Anweisung Methode führt zu vielen sauberen Code und die SQL-Injection Vorteile sind eine wirklich schöne Ergänzung.

Auch warum das Rad neu erfinden?

Anstatt ein Apostroph an sich verändernde zwei einfache Anführungszeichen (was aussieht wie), warum nicht nur um es zu einem Apostroph ändern, ein Angebot, oder ganz löschen?

So oder so, es ist ein bisschen von einer Flickschusterei ... vor allem wenn man berechtigterweise Dingen (wie Namen), die einfachen Anführungszeichen verwenden kann ...

Hinweis: Ihre Methode nimmt auch an alle auf Ihrer App arbeitet, erinnert sich immer eingegeben sanieren, bevor sie die Datenbank trifft, die wahrscheinlich die meiste Zeit nicht realistisch

.

Während Sie vielleicht eine Lösung finden, die für Strings arbeitet, für numerische Prädikate Sie müssen auch sicherstellen, dass sie vorbei sind nur in Zahlen (einfache Prüfung ist, kann es als int / double / dezimal analysiert werden?).

Es ist eine Menge zusätzlicher Arbeit.

Es könnte funktionieren, aber es scheint ein wenig kitschig zu mir. Ich würde empfehlen, verifing dass jede Saite durch Testen sie mit einem regulären Ausdruck gültig ist, statt.

Ja, Sie können, wenn ...

das Thema Nach dem Studium, ich denke Eingang hygienisiert, wie Sie sicher vorgeschlagen, aber nur unter diesen Regeln:

  1. Sie nie von den Benutzern String-Werte erlauben kommt etwas anderes zu werden als Zeichenketten (d vermeiden Konfigurationsoption geben: „Geben Sie zusätzliche SQL Spaltennamen / Ausdrücke hier:“). Werttypen außer Strings (Zahlen, Daten, ...):. Wandeln sie in ihre nativen Datentypen und bieten eine Routine für SQL wörtliche von jedem Datentyp

    • SQL-Anweisungen sind problematisch zu validieren
  2. Sie entweder nvarchar / nchar Spalten (und Präfix Stringliterale mit N) OR Grenzwerte gehen in varchar / char Spalten in ASCII-Zeichen nur (z throw Ausnahme beim Erstellen von SQL-Anweisung)

    • Auf diese Weise werden Sie die automatische Apostroph Konvertierung von CHAR (700) zu CHAR (39) (und vielleicht auch andere ähnliche Unicode-Hacks) werden vermieden
  3. Sie immer Wert Länge validieren tatsächliche Spaltenlänge (throw Exception aus, wenn länger)

    passen
    • Es wurde SQL-Fehler ein bekannter Defekt in SQL Server ermöglichen auf Verkürzungs geworfen zu umgehen (was zu automatischen Kürzen)
  4. stellen Sie sicher, dass SET QUOTED_IDENTIFIER immer ON

    • Vorsicht, ist es in Kraft Parse-Zeit genommen, das heißt auch in schwer zugänglichen Abschnitte des Codes

Die Einhaltung dieser 4 Punkte, sollten Sie sicher sein. Wenn Sie einen von ihnen verletzen, öffnet sich ein Weg für SQL-Injection.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top