Mir ist klar, dass parametrisierte SQL-Abfragen die optimale Methode sind, um Benutzereingaben zu bereinigen, wenn Abfragen erstellt werden, die Benutzereingaben enthalten. Ich frage mich jedoch, was falsch daran ist, Benutzereingaben zu übernehmen und einfache Anführungszeichen zu umgehen und die gesamte Zeichenfolge mit einfachen Anführungszeichen zu umgeben. Hier ist der Code:
sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"
Jedes einfache Anführungszeichen, das der Benutzer eingibt, wird durch doppelte einfache Anführungszeichen ersetzt, wodurch die Möglichkeit des Benutzers, die Zeichenfolge zu beenden, entfällt. Alle anderen eingegebenen Zeichen wie Semikolons, Prozentzeichen usw. sind Teil der Zeichenfolge und nicht tatsächlich als Teil des Befehls ausgeführt.
Wir verwenden Microsoft SQL Server 2000, für das das einfache Anführungszeichen meines Erachtens das einzige Zeichenfolgenbegrenzer und die einzige Möglichkeit ist, dem Zeichenfolgenbegrenzer zu entkommen. Daher gibt es keine Möglichkeit, etwas auszuführen, das der Benutzer eingibt.
Ich sehe keine Möglichkeit, einen SQL-Injection-Angriff dagegen zu starten, aber mir ist klar, dass, wenn dies so kugelsicher wäre, wie es mir scheint, jemand anderes bereits daran gedacht hätte und es gängige Praxis wäre.
Was ist los mit diesem Code? Gibt es eine Möglichkeit, einen SQL-Injection-Angriff nach dieser Desinfektionstechnik durchzuführen? Eine Benutzereingabe, die diese Technik ausnutzt, wäre sehr hilfreich.
AKTUALISIEREN:
Ich kenne immer noch keine Möglichkeit, einen SQL-Injection-Angriff gegen diesen Code effektiv zu starten. Einige Leute schlugen vor, dass ein Backslash einem einfachen Anführungszeichen entgehen und das andere die Zeichenfolge beenden würde, damit der Rest der Zeichenfolge als Teil des SQL-Befehls ausgeführt wird, und mir ist klar, dass diese Methode funktionieren würde, um SQL einzufügen eine MySQL-Datenbank, aber in SQL Server 2000 ist die einzige Möglichkeit (die ich gefunden habe), einem einfachen Anführungszeichen zu entkommen, ein anderes einfaches Anführungszeichen; Backslashes machen das nicht.
Und wenn es keine Möglichkeit gibt, das Entkommen des einfachen Anführungszeichens zu stoppen, wird keine der restlichen 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 wirklich mehr daran interessiert zu erfahren, warum die oben angegebene Methode nicht funktioniert. Wenn jemand einen bestimmten Weg kennt, um einen SQL-Injection-Angriff gegen diese Desinfektionsmethode durchzuführen, würde ich ihn gerne sehen.
Antworten:
Zuallererst ist es nur eine schlechte Übung. Eine Eingabevalidierung ist immer notwendig, aber auch immer zweifelhaft.
Schlimmer noch, die Validierung der Blacklist ist immer problematisch. Es ist viel besser, explizit und genau zu definieren, welche Werte / Formate Sie akzeptieren. Zugegeben, das ist nicht immer möglich - aber bis zu einem gewissen Grad muss es immer getan werden.
Einige Forschungsarbeiten zu diesem Thema:
Der Punkt ist, dass jede Blacklist, die Sie erstellen (und zu zulässige Whitelists), umgangen werden kann. Der letzte Link zu meinem Artikel zeigt Situationen, in denen sogar das Entkommen von Zitaten umgangen werden kann.
Auch wenn diese Situationen nicht auf Sie zutreffen, ist es immer noch eine schlechte Idee. Wenn Ihre App nicht trivial klein ist, müssen Sie sich außerdem um die Wartung und möglicherweise um ein gewisses Maß an Governance kümmern: Wie stellen Sie sicher, dass sie jederzeit und überall richtig ausgeführt wird?
Der richtige Weg, es zu tun:
quelle
sp_executesql
anstelle vonEXEC
). Das heißt, Sie können Ihre SQL-Anweisung dynamisch generieren, solange der verkettete Text nicht vom Benutzer stammt. Dies hat auch Leistungsvorteile;sp_executesql
unterstützt das Caching.Okay, diese Antwort bezieht sich auf die Aktualisierung der Frage:
Abgesehen davon, dass der MySQL-Backslash nicht mehr angezeigt wird - und wenn man bedenkt, dass es sich tatsächlich um MSSQL handelt, gibt es tatsächlich drei Möglichkeiten, wie SQL Ihren Code weiterhin einfügt
Berücksichtigen Sie, dass diese nicht alle jederzeit gültig sind und stark von Ihrem tatsächlichen Code abhängen:
Was Sie dann erhalten, ist der Benutzername, der maskiert und dann auf 20 Zeichen gekürzt wurde. Das Problem hier - ich werde mein Zitat in das 20. Zeichen (z. B. nach 19 a) stecken, und Ihr entkommenes Zitat wird gekürzt (im 21. Zeichen). Dann die SQL
In Kombination mit dem oben genannten fehlerhaften Benutzernamen befindet sich das Kennwort bereits außerhalb der Anführungszeichen und enthält nur die Nutzdaten direkt.
3. Unicode-Schmuggel - In bestimmten Situationen ist es möglich, ein übergeordnetes Unicode-Zeichen zu übergeben, das wie ein Zitat aussieht , es aber nicht ist - bis es in die Datenbank gelangt, wo es plötzlich ist . Da es sich bei der Validierung nicht um ein Zitat handelt, wird es einfach durchlaufen ... Weitere Informationen finden Sie in meiner vorherigen Antwort und einen Link zur ursprünglichen Forschung.
quelle
Kurz gesagt: Stellen Sie niemals Fragen, die sich selbst entziehen. 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.
quelle
Mir ist klar, dass dies eine lange Zeit ist, nachdem die Frage gestellt wurde, aber ..
Eine Möglichkeit, einen Angriff auf die Prozedur "Zitat das Argument" zu starten, ist das Abschneiden von Zeichenfolgen. Laut MSDN wird in SQL Server 2000 SP4 (und SQL Server 2005 SP1) eine zu lange Zeichenfolge stillschweigend abgeschnitten.
Wenn Sie eine Zeichenfolge zitieren, wird die Zeichenfolge größer. Jeder Apostroph wird wiederholt. Dies kann dann verwendet werden, um Teile des SQL aus dem Puffer zu verschieben. So können Sie Teile einer where-Klausel effektiv entfernen.
Dies ist wahrscheinlich vor allem in einem Szenario mit einer Benutzeradministrationsseite nützlich, in dem Sie die Anweisung "update" missbrauchen könnten, um nicht alle Überprüfungen durchzuführen, die sie durchführen sollte.
Wenn Sie sich also dazu entschließen, alle Argumente zu zitieren, stellen Sie sicher, dass Sie wissen, was mit den Zeichenfolgengrößen geschieht, und sorgen Sie dafür, 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. Und als Nebeneffekt erhalten Sie mit größerer Wahrscheinlichkeit bessere Cache-Treffer, da mehr Aussagen gleich aussehen. (Dies traf sicherlich auf Oracle 8 zu.)
quelle
Ich habe diese Technik verwendet, wenn es um die erweiterte Suche ging, bei der das Erstellen einer Abfrage von Grund auf die einzig praktikable 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 ihre zulässigen Werte als GUI-Steuerelemente angezeigt werden, um den Lernschwellenwert für Benutzer zu verringern.)
An sich ist es sicher AFAIK. Wie ein anderer Antwortender betonte, müssen Sie sich möglicherweise auch mit dem Entweichen von Rücktasten befassen (allerdings nicht, wenn Sie die Abfrage zumindest mit ADO oder ADO.NET an SQL Server übergeben - kann nicht für alle Datenbanken oder Technologien bürgen).
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 Fallen 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!) Beim Erstellen der SQL-Abfrage zu bereinigen.
In den meisten Fällen ist die Parameterbindung jedoch der richtige Weg - sie ist einfach einfacher.
quelle
Input-Hygiene ist nicht etwas, das Sie halbherzig machen wollen. Benutze deinen ganzen Arsch. Verwenden Sie reguläre Ausdrücke für Textfelder. Versuchen Sie, Ihre Zahlen auf den richtigen numerischen Typ zu übertragen, und melden Sie einen Validierungsfehler, wenn dies nicht funktioniert. Es ist sehr einfach, in Ihrer Eingabe nach Angriffsmustern zu suchen, z. B. '-. Angenommen, alle Eingaben des Benutzers sind feindlich.
quelle
flavors
dieser Seite).Es ist sowieso eine schlechte Idee, wie Sie zu wissen scheinen.
Was ist mit so etwas wie dem Zitat in einer solchen Zeichenfolge zu entkommen: \ '
Ihr Ersatz würde führen zu: \ ''
Wenn der Backslash dem ersten Anführungszeichen entgeht, hat das zweite Anführungszeichen die Zeichenfolge beendet.
quelle
Einfache Antwort: Es wird manchmal funktionieren, aber nicht immer. Sie möchten die White-List-Validierung für alles verwenden, was Sie tun, aber mir ist klar, dass dies nicht immer möglich ist. Sie sind daher gezwungen, die beste Blacklist zu verwenden. Ebenso möchten Sie parametrisierte gespeicherte Prozesse in allem verwenden , aber dies ist wiederum nicht immer möglich, sodass Sie gezwungen sind, sp_execute mit Parametern zu verwenden.
Es gibt Möglichkeiten, um jede verwendbare Blacklist zu umgehen, die Sie erstellen können (und einige Whitelists auch).
Eine anständige Beschreibung finden Sie hier: http://www.owasp.org/index.php/Top_10_2007-A2
Wenn Sie dies als schnelle Lösung tun müssen, um Zeit zu haben, eine echte zu installieren, tun Sie es. Aber glaube nicht, dass du in Sicherheit bist.
quelle
Es gibt zwei Möglichkeiten, dies zu tun, ohne Ausnahmen, um vor SQL-Injektionen sicher zu sein. vorbereitete Anweisungen oder vorprogrammierte gespeicherte Prozeduren.
quelle
Wenn Sie parametrisierte Abfragen zur Verfügung haben, sollten Sie diese jederzeit verwenden. Es genügt eine einzige Abfrage, um durch das Netz zu rutschen, und Ihre Datenbank ist gefährdet.
quelle
Ja, das sollte funktionieren, bis jemand SET QUOTED_IDENTIFIER OFF ausführt und ein doppeltes Anführungszeichen für Sie verwendet.
Bearbeiten: Es ist nicht so einfach, dem böswilligen Benutzer nicht zu erlauben, zitierte Bezeichner zu deaktivieren:
Es gibt viele Möglichkeiten, wie QUOTED_IDENTIFIER ausgeschaltet werden kann, ohne dass Sie es unbedingt wissen. Zugegeben - dies ist nicht der Exploit für rauchende Waffen, den Sie suchen, aber es ist eine ziemlich große Angriffsfläche. Wenn Sie auch doppelten Anführungszeichen entkommen sind, sind wir natürlich wieder da, wo wir angefangen haben. ;)
quelle
Ihre Verteidigung würde scheitern, wenn:
(Im letzteren Fall müsste es sich um etwas handeln, das erst nach dem Ersetzen erweitert wurde.)
quelle
Patrick, fügen Sie einfache Anführungszeichen um ALLE Eingaben hinzu, sogar um numerische Eingaben? Wenn Sie eine numerische Eingabe haben, diese aber nicht in einfache Anführungszeichen setzen, haben Sie eine Belichtung.
quelle
Was für ein hässlicher Code wäre all diese Bereinigung der Benutzereingaben! Dann der klobige StringBuilder für die SQL-Anweisung. Die vorbereitete Anweisungsmethode führt zu viel saubererem Code, und die Vorteile von SQL Injection sind eine wirklich schöne Ergänzung.
Auch warum das Rad neu erfinden?
quelle
Anstatt ein einzelnes Zitat 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.
In jedem Fall ist es ein bisschen kludge ... besonders wenn Sie legitimerweise 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, was wahrscheinlich die meiste Zeit nicht realistisch ist.
quelle
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 Überprüfung ist, ob sie als int / double / decimal analysiert werden können?).
Es ist viel zusätzliche Arbeit.
quelle
Es könnte funktionieren, aber es scheint mir ein wenig hokey. Ich würde empfehlen, zu überprüfen, ob jede Zeichenfolge gültig ist, indem Sie sie stattdessen mit einem regulären Ausdruck testen.
quelle
Ja, Sie können, wenn ...
Nach dem Studium des Themas halte ich eine von Ihnen vorgeschlagene bereinigte Eingabe für sicher, jedoch nur nach folgenden Regeln:
Sie lassen niemals zu, dass Zeichenfolgenwerte, die von Benutzern stammen, zu etwas anderem als Zeichenfolgenliteralen werden (dh geben Sie keine Konfigurationsoption an: "Geben Sie hier zusätzliche SQL-Spaltennamen / Ausdrücke ein:"). Andere Werttypen als Zeichenfolgen (Zahlen, Datumsangaben, ...): Konvertieren Sie sie in ihre nativen Datentypen und stellen Sie für jeden Datentyp eine Routine für das SQL-Literal bereit.
Sie verwenden entweder
nvarchar
/nchar
columns (und Präfix-String-Literale mitN
) ODER begrenzen Werte, die invarchar
/char
column gehen, nur für ASCII-Zeichen (z. B. Ausnahme beim Erstellen einer SQL-Anweisung)Sie überprüfen die Wertelänge immer so, dass sie zur tatsächlichen Spaltenlänge passt (Ausnahme auslösen, wenn länger)
Sie stellen sicher, dass
SET QUOTED_IDENTIFIER
das immer so istON
Wenn Sie diese 4 Punkte einhalten, sollten Sie sicher sein. Wenn Sie gegen eine dieser Bestimmungen verstoßen, wird eine Möglichkeit zur SQL-Injection geöffnet.
quelle