it-swarm.com.de

Wie kann die Bereinigung, bei der einfache Anführungszeichen nicht berücksichtigt werden, durch SQL Injection in SQL Server verhindert werden?

Zunächst ist mir klar, dass parametrisierte Abfragen die beste Option sind, aber ich frage mich, was die Strategie, die ich hier vorstelle, anfällig macht. Die Leute bestehen darauf, dass die folgende Lösung nicht funktioniert, also suche ich ein Beispiel dafür, warum es nicht funktioniert.

Welche Art von Injection kann dies verhindern, wenn dynamischer SQL-Code mithilfe der folgenden Escapezeichen erstellt wird, bevor er an einen SQL Server gesendet wird?

string userInput= "N'" + userInput.Replace("'", "''") + "'"

Eine ähnliche Frage wurde beantwortet hier , aber ich glaube nicht, dass eine der Antworten hier zutrifft.

Es ist in SQL Server nicht möglich, das einfache Anführungszeichen mit einem "\" zu ersetzen.

Ich glaube, SQL Smuggling mit Unicode (skizziert hier ) würde durch die Tatsache vereitelt, dass der produzierte String markiert ist als Unicode durch das N vor dem einfachen Anführungszeichen. Soweit ich weiß, gibt es keine anderen Zeichensätze, die SQL Server automatisch in ein einfaches Anführungszeichen übersetzen würde. Ohne ein einfaches Anführungszeichen glaube ich nicht, dass eine Injektion möglich ist.

Ich glaube nicht, dass das Abschneiden von Strings ein brauchbarer Vektor ist. SQL Server wird das Abschneiden mit Sicherheit nicht durchführen, da die maximale Größe für ein nvarchar 2 GB beträgt laut Microsoft . Eine 2-GB-Zeichenfolge ist in den meisten Situationen nicht möglich und in meiner unmöglich.

Second Order Injection könnte möglich sein, aber ist es möglich, wenn:

  1. Alle in die Datenbank eingehenden Daten werden mit der oben beschriebenen Methode bereinigt
  2. Werte aus der Datenbank werden niemals an dynamisches SQL angehängt (warum sollten Sie das überhaupt tun, wenn Sie nur auf den Tabellenwert im statischen Teil einer dynamischen SQL-Zeichenfolge verweisen können?).

Ich schlage nicht vor, dass dies besser ist als oder eine Alternative zur Verwendung parametrisierter Abfragen, aber ich möchte wissen, wie anfällig das ist, was ich dargelegt habe. Irgendwelche Ideen?

64
GBleaney

Es gibt einige Fälle, in denen diese Escape-Funktion fehlschlägt. Das offensichtlichste ist, wenn kein einfaches Anführungszeichen verwendet wird:

string table= "\"" + table.Replace("'", "''") + "\""
string var= "`" + var.Replace("'", "''") + "`"
string index= " " + index.Replace("'", "''") + " "
string query = "select * from `"+table+"` where name=\""+var+"\" or id="+index

In diesem Fall können Sie mit einem doppelten Anführungszeichen (Back-Tick) "ausbrechen". Im letzten Fall gibt es nichts, woraus man "ausbrechen" könnte. Sie können also einfach 1 union select password from users-- Oder eine beliebige SQL-Nutzlast schreiben, die der Angreifer wünscht.

Die nächste Bedingung, bei der diese Escape-Funktion fehlschlägt, besteht darin, dass nach dem Escape der Zeichenfolge eine Teilzeichenfolge verwendet wird (und yes Ich habe in eine solche Sicherheitsanfälligkeit gefunden das wilde):

string userPassword= userPassword.Replace("'", "''")
string userName= userInput.Replace("'", "''")
userName = substr(userName,0,10)
string query = "select * from users where name='"+userName+"' and password='"+userPassword+"'";

In diesem Fall wird ein Benutzername von abcdefgji' Durch die Escape-Funktion in abcdefgji'' Umgewandelt und dann durch Verwenden der Unterzeichenfolge wieder in abcdefgji' Umgewandelt. Dies kann ausgenutzt werden, indem der Kennwortwert auf eine beliebige SQL-Anweisung gesetzt wird. In diesem Fall wird or 1=1-- Als SQL und der Benutzername als abcdefgji'' and password= Interpretiert. Die resultierende Abfrage lautet wie folgt:

select * from users where name='abcdefgji'' and password=' or 1=1-- 

T-SQL und andere fortschrittliche SQL-Injektionstechniken wurden bereits erwähnt. Advanced SQL Injection in SQL Server-Anwendungen ist ein großartiges Papier, und Sie sollten es lesen, wenn Sie es noch nicht getan haben.

Das letzte Problem sind Unicode-Angriffe. Diese Schwachstellenklasse entsteht, weil die Escape-Funktion keine Multibyte-Codierung kennt und dies von einem Angreifer verwendet werden kann, um das Escape-Zeichen zu "verbrauchen" . Das Voranstellen eines "N" an der Zeichenfolge hilft nicht, da dies den Wert von Mehrbyte-Zeichen später in der Zeichenfolge nicht beeinflusst. Diese Art von Angriff ist jedoch sehr ungewöhnlich, da die Datenbank so konfiguriert sein muss, dass sie GBK-Unicode-Zeichenfolgen akzeptiert (und ich bin nicht sicher, ob MS-SQL dies kann).

Die Code-Injection zweiter Ordnung ist weiterhin möglich. Dieses Angriffsmuster wird durch vertrauenswürdige angreifergesteuerte Datenquellen erstellt. Escaping wird verwendet, um Steuerzeichen als Zeichenliteral darzustellen. Wenn der Entwickler vergisst, einen aus einem select erhaltenen Wert zu umgehen, und diesen Wert dann in einer anderen Abfrage verwendet, hat der Angreifer ein bam Zeichen wörtliches einfaches Anführungszeichen zur Verfügung.

Teste alles, vertraue nichts.

40
rook

Mit einigen zusätzlichen Bestimmungen ist Ihr Ansatz nicht anfällig für SQL-Injection. Der wichtigste zu berücksichtigende Angriffsvektor ist SQL-Schmuggel. SQL Smuggling tritt auf, wenn ähnliche Unicode-Zeichen auf unerwartete Weise übersetzt werden (z. B. "Ändern in"). Es gibt mehrere Stellen, an denen ein Anwendungsstapel für SQL Smuggling anfällig sein kann.

  • Behandelt die Programmiersprache Unicode-Zeichenfolgen angemessen? Wenn die Sprache Unicode-fähig ist, kann sie ein Byte in einem Unicode-Zeichen als einfaches Anführungszeichen falsch identifizieren und es maskieren.

  • Behandelt die Client-Datenbankbibliothek (z. B. ODBC usw.) Unicode-Zeichenfolgen angemessen? System.Data.SqlClient im .Net-Framework, aber wie sieht es mit alten Bibliotheken aus der Windows 95-Ära aus? Es gibt tatsächlich ODBC - Bibliotheken von Drittanbietern. Was passiert, wenn der ODBC - Treiber Unicode in der Abfragezeichenfolge nicht unterstützt?

  • Wird die Eingabe von der Datenbank korrekt verarbeitet? Moderne SQL-Versionen sind immun gegen die Annahme, dass Sie N '' verwenden, aber wie steht es mit SQL 6.5? SQL 7.0? Mir sind keine besonderen Schwachstellen bekannt, dies war jedoch in den 90er Jahren für Entwickler nicht der Fall.

  • Pufferüberlauf? Ein weiteres Problem ist, dass die angegebene Zeichenfolge länger als die ursprüngliche Zeichenfolge ist. In welcher Version von SQL Server wurde die 2-GB-Grenze für die Eingabe eingeführt? Davor war was die Grenze? Was geschah bei älteren SQL-Versionen, wenn eine Abfrage den Grenzwert überschritt? Gibt es aus Sicht der Netzwerkbibliothek Beschränkungen für die Länge einer Abfrage? Oder über die Länge des Strings in der Programmiersprache?

  • Gibt es Spracheinstellungen, die sich auf den Vergleich in der Funktion Replace () auswirken? .Net führt für die Funktion Replace () immer einen binären Vergleich durch. Wird das immer so sein? Was passiert, wenn eine zukünftige Version von .NET das Überschreiben dieses Verhaltens auf der Ebene app.config unterstützt? Was wäre, wenn wir anstelle von Replace () einen regulären Ausdruck verwenden würden, um ein einfaches Anführungszeichen einzufügen? Beeinflusst die Ländereinstellung des Computers diesen Vergleich? Wenn sich das Verhalten geändert hat, ist es möglicherweise nicht anfällig für SQL Injection. Möglicherweise wurde die Zeichenfolge jedoch versehentlich bearbeitet, indem ein Uni-Code-Zeichen, das wie ein einfaches Anführungszeichen aussah, in ein einfaches Anführungszeichen geändert wurde, bevor es die DB erreichte.

Angenommen, Sie verwenden die System.String.Replace () - Funktion in C # für die aktuelle Version von .Net mit der integrierten SqlClient-Bibliothek für eine aktuelle Version von SQL Server (2005-2012) verletzlich. Wenn Sie anfangen, Dinge zu ändern, können keine Versprechungen gemacht werden. Der parametrisierte Abfrageansatz ist der richtige Ansatz für Effizienz, Leistung und (in einigen Fällen) für Sicherheit.

WARNING Die obigen Kommentare sind keine Billigung dieser Technik. Es gibt mehrere andere sehr gute Gründe, warum dies der falsche Ansatz zum Generieren von SQL ist. Eine nähere Betrachtung ist jedoch nicht Gegenstand dieser Frage.

BENUTZEN SIE DIESE TECHNIK NICHT FÜR NEUE ENTWICKLUNGEN.

BENUTZEN SIE DIESE TECHNIK NICHT FÜR NEUE ENTWICKLUNGEN.

BENUTZEN SIE DIESE TECHNIK NICHT FÜR NEUE ENTWICKLUNGEN.

17
StrayCatDBA

Verwenden von Abfrageparametern ist besser, einfacher und schneller als das Entweichen von Anführungszeichen.


Bezüglich Ihres Kommentars sehe ich, dass Sie die Parametrisierung anerkannt haben, sie verdient jedoch Nachdruck. Warum sollten Sie das Escaping verwenden, wenn Sie parametrieren können?

Suchen Sie in Erweiterte SQL-Injection in SQL Server-Anwendungen nach dem Wort "replace" im Text, und lesen Sie ab diesem Zeitpunkt einige Beispiele, in denen Entwickler versehentlich SQL-Injection-Angriffe zugelassen haben, auch nachdem sie der Benutzereingabe entkommen sind.


Es gibt einen Edge-Fall, in dem Anführungszeichen mit \ Eine Sicherheitsanfälligkeit darstellen, da \ In einigen Zeichensätzen die Hälfte eines gültigen Mehrbytezeichens darstellt. Dies gilt jedoch nicht für Ihren Fall, da \ Nicht das Escapezeichen ist.

Wie bereits erwähnt, können Sie Ihrem SQL auch andere dynamische Inhalte als ein Zeichenfolgen- oder Datumsliteral hinzufügen. Tabellen- oder Spalten-IDs werden in SQL durch " Oder in Microsoft/Sybase durch [] Begrenzt. SQL-Schlüsselwörter haben natürlich keine Begrenzer. In diesen Fällen empfehle ich Whitelisting die zu interpolierenden Werte.

Unterm Strich ist das Entkommen ist eine wirksame Verteidigung, wenn Sie sicherstellen können, dass Sie es konsequent tun. Das ist das Risiko, dass einer der Entwickler Ihrer Anwendung einen Schritt auslässt und unsicher Zeichenfolgen interpoliert.

Gleiches gilt natürlich auch für andere Methoden wie die Parametrierung. Sie sind nur dann wirksam, wenn Sie sie konsequent anwenden. Ich finde jedoch, dass es einfacher ist, Parameter schneller zu verwenden, als die richtige Art der Flucht zu finden. Und Entwickler verwenden mit größerer Wahrscheinlichkeit eine bequeme Methode, die sie nicht verlangsamt.

9
Bill Karwin

SQL-Injection tritt auf, wenn vom Benutzer bereitgestellte Eingaben als Befehle interpretiert werden. Hier bedeutet Befehl alles, was nicht als erkanntes Datentyp Literal interpretiert wird.

Wenn Sie die Benutzereingabe nur in Datenliteralen, insbesondere in Zeichenfolgenliteralen, verwenden, wird die Benutzereingabe nur dann als etwas anderes als Zeichenfolgendaten interpretiert, wenn der Zeichenfolgenliteralkontext verlassen werden kann. Bei Zeichenketten- oder Unicode-String-Literalen ist dies das einfache Anführungszeichen, das die Literaldaten einschließt, während eingebettete einfache Anführungszeichen mit zwei einfachen Anführungszeichen dargestellt werden müssen.

Um einen String-Literal-Kontext zu verlassen, müsste ein einzelnes Anführungszeichen (sic) angegeben werden, da zwei einzelne Anführungszeichen als String-Literal-Daten und nicht als String-Literal-Endbegrenzer interpretiert werden.

Wenn Sie also ein einzelnes Anführungszeichen in den vom Benutzer angegebenen Daten durch zwei einzelne Anführungszeichen ersetzen, kann der Benutzer den String-Literal-Kontext nicht verlassen.

4
Gumbo

SQL Injection kann über Unicode erfolgen. Wenn die Web-App eine URL wie diese hat:

http: // mywebapp/widgets /? Code = ABC

das SQL wie select * aus Widgets erzeugt, bei denen Code = 'ABC'

aber ein Hacker betritt dies:

http: // mywebapp/widgets /? Code = ABC% CA% BC; drop table widgets--

der SQL-Code sieht wie folgt aus: select * from widgets where Code = 'ABC'; drop table widgets-- '

und SQL Server führt zwei SQL-Anweisungen aus. Eine für die Auswahl und eine für den Abwurf. Ihr Code konvertiert wahrscheinlich den url-codierten% CA% BC in den Unicode U02BC, bei dem es sich um einen "Modifikatorbuchstaben-Apostroph" handelt. Die Ersetzen-Funktion in .Net behandelt dies NICHT als einfaches Anführungszeichen. Microsoft SQL Server behandelt es jedoch wie ein einfaches Anführungszeichen. Hier ist ein Beispiel, das wahrscheinlich SQL Injection zulässt:

string badValue = ((char)0x02BC).ToString();
badValue = badValue + ";delete from widgets--";
string sql = "SELECT * FROM WIDGETS WHERE ID=" + badValue.Replace("'","''");
TestTheSQL(sql);
3
Rob Kraft

Es gibt wahrscheinlich keine 100% sichere Möglichkeit, wenn Sie Zeichenfolgen verketten. Sie können versuchen, den Datentyp für jeden Parameter zu überprüfen. Wenn alle Parameter eine solche Validierung bestehen, fahren Sie mit der Ausführung fort. Wenn Ihr Parameter beispielsweise int sein sollte und Sie etwas erhalten, das nicht in int konvertiert werden kann, lehnen Sie es einfach ab.

Dies funktioniert jedoch nicht, wenn Sie nvarchar-Parameter akzeptieren.

Wie andere schon betonten. Am sichersten ist es, eine parametrisierte Abfrage zu verwenden.

2
George Wesley