Zu Beginn bin ich mir bewusst, dass parametrisierte Abfragen die beste Option sind, aber ich frage mich, was die unten dargestellte Strategie anfällig macht. Die Leute bestehen darauf, dass die unten stehende Lösung nicht funktioniert, deshalb suche ich nach einem Beispiel dafür, warum dies nicht der Fall ist.
Welche Art von Injection kann dies verhindern, wenn dynamisches SQL mit dem folgenden Escapezeichen in Code eingebaut wird, bevor es an einen SQL Server gesendet wird?
string userInput= "N'" + userInput.Replace("'", "''") + "'"
Eine ähnliche Frage wurde hier beantwortet , aber ich glaube nicht, dass eine der Antworten hier zutreffend ist.
In SQL Server ist es nicht möglich, das einfache Anführungszeichen mit einem "\" zu versehen.
Ich glaube, SQL-Schmuggel mit Unicode ( hier beschrieben ) würde durch die Tatsache vereitelt, dass die erzeugte Zeichenfolge durch das N vor dem einfachen Anführungszeichen als Unicode markiert wird. Soweit ich weiß, gibt es keine anderen Zeichensätze, die SQL Server automatisch in ein einfaches Anführungszeichen übersetzt. Ohne ein einfaches Zitat glaube ich nicht, dass eine Injektion möglich ist.
Ich glaube auch nicht, dass String Truncation ein brauchbarer Vektor ist. SQL Server wird das Abschneiden sicherlich nicht durchführen, da die maximale Größe für a laut Microsoftnvarchar
2 GB beträgt . Eine 2-GB-Zeichenfolge ist in den meisten Situationen nicht und in meinen nicht möglich.
Eine Injektion zweiter Ordnung könnte möglich sein, aber ist es möglich, wenn:
- Alle Daten, die in die Datenbank gelangen, werden mit der oben beschriebenen Methode bereinigt
- 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 behaupte nicht, dass dies besser als oder eine Alternative zur Verwendung parametrisierter Abfragen ist, aber ich möchte wissen, wie anfällig das, was ich skizziert habe, ist. Irgendwelche Ideen?
quelle
"SELECT * FROM MyTable WHERE Field = " + userInput
wannuserInput
ist0; DROP TABLE OhNo;
.Antworten:
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, einem Back-Tick, "ausbrechen". Im letzten Fall gibt es nichts,
1 union select password from users--
woraus man "ausbrechen" kann, sodass Sie einfach schreiben können oder welche SQL-Nutzlast der Angreifer wünscht.Die nächste Bedingung, bei der diese Escape-Funktion fehlschlägt, ist, wenn eine Unterzeichenfolge nach dem Escapezeichen der Zeichenfolge verwendet wird (und ja, ich habe solche Sicherheitslücken in freier Wildbahn gefunden):
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 Falle ein Benutzername
abcdefgji'
wird in umgewandelt werdenabcdefgji''
durch die Escape - Funktion und dann verwandelte sich in zurück ,abcdefgji'
indem sie die Unterkette. Dies kann ausgenutzt werden, indem der Kennwortwert auf eine beliebige SQL-Anweisung gesetzt wird. In diesem Fall wirdor 1=1--
dies als SQL und der Benutzername als interpretiertabcdefgji'' and password=
. 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. Erweiterte SQL-Injection in SQL Server-Anwendungen ist ein großartiges Dokument, das Sie lesen sollten, wenn Sie es noch nicht getan haben.
Das letzte Problem sind Unicode-Angriffe. Diese Klasse von Sicherheitslücken tritt auf, weil die Escape-Funktion keine Multi-Byte-Codierung kennt und dies von einem Angreifer verwendet werden kann, um das Escape-Zeichen zu "verbrauchen" . Das Voranstellen eines "N" an die Zeichenfolge hilft nicht, da dies den Wert von Mehrbyte-Zeichen später in der Zeichenfolge nicht beeinflusst. Diese Art von Angriff ist jedoch sehr selten, da die Datenbank so konfiguriert werden muss, dass GBK-Unicode-Zeichenfolgen akzeptiert werden (und ich bin nicht sicher, ob MS-SQL dies kann).
Code-Injection zweiter Ordnung ist weiterhin möglich. Dieses Angriffsmuster wird durch Vertrauen in vom Angreifer kontrollierte Datenquellen erstellt. Escaping wird verwendet, um Steuerzeichen als Zeichenliteral darzustellen. Wenn die Entwickler vergessen einen Wert von a erhalten zu entkommen
select
und verwendet dann diesen Wert in einer anderen Abfrage dann bam die Angreifer einen Zeichenliteral Apostroph zur Verfügung stehen werden.Teste alles, vertraue nichts.
quelle
'
als Zeichenfolgenbegrenzer akzeptiert . Die Verwendung von Häkchen oder doppeltem Anführungszeichen würde dem Angreifer nicht helfenMit einigen zusätzlichen Bestimmungen ist Ihr oben beschriebener Ansatz nicht anfällig für SQL-Injection. Der wichtigste Angriffsvektor ist der SQL-Schmuggel. SQL-Schmuggel 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 nicht Unicode-fähig ist, kann sie ein Byte in einem Unicode-Zeichen als einfaches Anführungszeichen falsch identifizieren und es umgehen.
Behandelt die Client-Datenbankbibliothek (z. B. ODBC usw.) Unicode-Zeichenfolgen ordnungsgemäß? System.Data.SqlClient im .Net-Framework funktioniert, aber wie steht es mit alten Bibliotheken aus der Windows 95-Ära? ODBC-Bibliotheken von Drittanbietern existieren tatsächlich. Was passiert, wenn der ODBC-Treiber keinen Unicode in der Abfragezeichenfolge unterstützt?
Behandelt die DB die Eingabe korrekt? Moderne Versionen von SQL sind immun, wenn Sie N '' verwenden, aber was ist mit SQL 6.5? SQL 7.0? Mir sind keine besonderen Sicherheitslücken bekannt, aber dies war in den 90er Jahren für Entwickler nicht auf dem Radar.
Puffer läuft über? Ein weiteres Problem ist, dass die Zeichenfolge in Anführungszeichen länger als die ursprüngliche Zeichenfolge ist. In welcher Version von SQL Server wurde das 2-GB-Limit für die Eingabe eingeführt? Was war vorher die Grenze? Was ist bei älteren SQL-Versionen passiert, wenn eine Abfrage das Limit überschritten hat? Gibt es Einschränkungen für die Länge einer Abfrage aus Sicht der Netzwerkbibliothek? Oder auf die Länge der Zeichenfolge in der Programmiersprache?
Gibt es Spracheinstellungen, die sich auf den in der Funktion Replace () verwendeten Vergleich auswirken? .Net führt immer einen binären Vergleich für die Funktion Replace () 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? Beeinflussen die Gebietsschemaeinstellungen des Computers diesen Vergleich? Wenn eine Verhaltensänderung aufgetreten ist, ist sie möglicherweise nicht anfällig für SQL-Injection. Möglicherweise wurde die Zeichenfolge jedoch versehentlich bearbeitet, indem ein Unicode-Zeichen, das wie ein einfaches Anführungszeichen aussah, in ein einfaches Anführungszeichen geändert wurde, bevor es jemals die Datenbank erreichte.
Angenommen, Sie verwenden die Funktion System.String.Replace () in C # in der aktuellen Version von .Net mit der integrierten SqlClient-Bibliothek für eine aktuelle Version von SQL Server (2005-2012) anfällig. 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) Sicherheit.
WARNUNG Die obigen Kommentare sind keine Bestätigung dieser Technik. Es gibt mehrere andere sehr gute Gründe, warum dies der falsche Ansatz zum Generieren von SQL ist. Ihre Detaillierung liegt jedoch außerhalb des Rahmens dieser Frage.
VERWENDEN SIE DIESE TECHNIK NICHT FÜR NEUE ENTWICKLUNGEN.
VERWENDEN SIE DIESE TECHNIK NICHT FÜR NEUE ENTWICKLUNGEN.
VERWENDEN SIE DIESE TECHNIK NICHT FÜR NEUE ENTWICKLUNGEN.
quelle
CREATE LOGIN
bei Neuentwicklungen verwenden?Die Verwendung von Abfrageparametern ist besser, einfacher und schneller als das Anhalten von Anführungszeichen.
In Bezug auf Ihren Kommentar sehe ich, dass Sie die Parametrisierung anerkannt haben, aber sie verdient Hervorhebung. Warum sollten Sie Escape verwenden, wenn Sie parametrisieren können?
In Advanced SQL Injection Suchen Sie in SQL Server-Anwendungen nach dem Wort "Ersetzen" im Text und lesen Sie ab diesem Zeitpunkt einige Beispiele, in denen Entwickler versehentlich SQL-Injection-Angriffe zugelassen haben, selbst nachdem sie Benutzereingaben entgangen sind.
Es gibt einen Randfall, in dem das Entkommen von Anführungszeichen
\
zu einer Sicherheitsanfälligkeit führt, da\
in einigen Zeichensätzen die Hälfte eines gültigen Mehrbyte-Zeichens wird. Dies gilt jedoch nicht für Ihren Fall, da\
es sich nicht um den entkommenden Charakter handelt.Wie andere bereits erwähnt haben, fügen Sie Ihrer SQL möglicherweise auch dynamischen Inhalt für etwas anderes als ein Zeichenfolgenliteral oder ein Datumsliteral hinzu. Tabellen- oder Spaltenbezeichner werden
"
in SQL oder[
]
in Microsoft / Sybase durch begrenzt. SQL-Schlüsselwörter haben natürlich keine Trennzeichen. In diesen Fällen empfehle ich, die zu interpolierenden Werte auf die Whitelist zu setzen.Fazit ist , dass Flucht ist eine wirksame Verteidigung, wenn Sie sicherstellen können , dass Sie es konsequent tun. Das ist das Risiko: Einer der Entwickler Ihrer Anwendung kann einen Schritt weglassen und eine String-Interpolation unsicher durchführen.
Gleiches gilt natürlich auch für andere Methoden wie die Parametrisierung. Sie sind nur dann wirksam, wenn Sie sie konsequent ausführen. Aber ich finde es einfacher und schneller, Parameter zu verwenden, als die richtige Art der Flucht herauszufinden. Entwickler verwenden eher eine Methode, die praktisch ist und sie nicht verlangsamt.
quelle
SQL-Injection tritt auf, wenn vom Benutzer bereitgestellte Eingaben als Befehle interpretiert werden. Hier bedeutet Befehl alles, was nicht als erkanntes Datentypliteral interpretiert wird .
Wenn Sie die Benutzereingabe nur in Datenliteralen verwenden, insbesondere nur in Zeichenfolgenliteralen, wird die Benutzereingabe nur dann als etwas anderes als Zeichenfolgendaten interpretiert, wenn sie den Zeichenfolgenliteralkontext verlassen kann. Bei Zeichenfolgen- oder Unicode-Zeichenfolgenliteralen ist es 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 einfaches Anführungszeichen (sic) angegeben werden, da zwei einfache 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 einfache Anführungszeichen ersetzen, kann der Benutzer den Zeichenfolgenliteral-Kontext nicht verlassen.
quelle
SQL Injection kann über Unicode erfolgen. Wenn die Web-App eine URL wie diese hat:
http: // mywebapp / widgets /? Code = ABC
Dies erzeugt SQL wie select * aus Widgets, wobei Code = 'ABC'.
aber ein Hacker betritt dies:
http: // mywebapp / widgets /? Code = ABC% CA% BC; Tabellen-Widgets löschen--
Das SQL sieht so aus, als würde es * aus Widgets auswählen, wobei Code = 'ABC'; Tabellen-Widgets löschen-- '
und SQL Server führt zwei SQL-Anweisungen aus. Eine zum Auswählen und eine zum Löschen. Ihr Code konvertiert wahrscheinlich das URL-codierte% CA% BC in den Unicode U02BC, bei dem es sich um einen "Modifikator-Buchstaben-Apostroph" handelt. Die Ersetzungsfunktion 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 ermöglicht:
string badValue = ((char)0x02BC).ToString(); badValue = badValue + ";delete from widgets--"; string sql = "SELECT * FROM WIDGETS WHERE ID=" + badValue.Replace("'","''"); TestTheSQL(sql);
quelle
Es gibt wahrscheinlich keinen 100% sicheren Weg, wenn Sie eine Zeichenfolgenverkettung durchführen. 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 vom Typ 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 bereits betonten. Am sichersten ist die Verwendung einer parametrisierten Abfrage.
quelle