Dieser Code funktioniert ordnungsgemäß, weil er:
- Parametriert und
- Keine Dynamic SQL
Damit SQL Injection zu arbeiten, müssen Sie eine Abfrage - String bauen (die Sie nicht tun werden) und nicht übersetzen einzelne Apostrophe ( '
) in entkam-Apostrophe ( ''
) (die über die Eingangsparameter entkam).
Bei dem Versuch, einen "kompromittierten" Wert einzugeben, handelt es sich bei der 'Male; DROP TABLE tblActor'
Zeichenfolge lediglich um eine einfache Zeichenfolge.
Nun, wenn Sie etwas in der Art von:
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = N'SELECT fields FROM table WHERE field23 = '
+ @InputParam;
EXEC(@SQL);
dann , dass wäre anfällig für SQL - Injection , da die Abfrage nicht in dem aktuellen ist, vorab geparsten Kontext; Diese Abfrage ist im Moment nur eine weitere Zeichenfolge. Der Wert von @InputParam
könnte also '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;
ein Problem darstellen, da diese Abfrage wie folgt gerendert und ausgeführt wird:
SELECT fields FROM table WHERE field23 = '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;
Dies ist einer von mehreren Hauptgründen für die Verwendung von Stored Procedures: von Natur aus sicherer (vorausgesetzt, Sie umgehen diese Sicherheit nicht, indem Sie Abfragen wie oben gezeigt erstellen, ohne die Werte der verwendeten Parameter zu validieren). Wenn Sie jedoch dynamisches SQL erstellen müssen, sollten Sie dies auch folgendermaßen parametrisieren sp_executesql
:
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = N'SELECT fields FROM table WHERE field23 = @SomeDate_tmp';
EXEC sp_executesql
@SQL,
N'SomeDate_tmp DATETIME',
@SomeDate_tmp = @InputParam;
Bei Verwendung dieses Ansatzes würde jemand, der versucht, '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;
einen DATETIME
Eingabeparameter zu übergeben, beim Ausführen der gespeicherten Prozedur einen Fehler erhalten. Oder selbst wenn die gespeicherte Prozedur @InputParameter
als akzeptiert NVARCHAR(100)
würde, müsste sie in eine konvertiert DATETIME
werden, um in diesen sp_executesql
Aufruf überzugehen. Und selbst wenn der Parameter in Dynamic SQL ein Zeichenfolgentyp ist, wird bei der gespeicherten Prozedur in erster Linie jedes einzelne Apostroph automatisch zu einem doppelten Apostroph maskiert.
Es gibt eine weniger bekannte Angriffsart, bei der der Angreifer versucht, das Eingabefeld mit Apostrophen auszufüllen, sodass eine Zeichenfolge in der gespeicherten Prozedur, die zum Erstellen von Dynamic SQL verwendet werden würde, jedoch als zu klein deklariert wird, nicht für alles passen kann und schiebt den abschließenden Apostroph heraus und endet irgendwie mit der richtigen Anzahl von Apostrophen, um nicht länger innerhalb der Zeichenkette "entkommen" zu werden. Dies wird als SQL-Kürzung bezeichnet und wurde in einem Artikel des MSDN-Magazins mit dem Titel "Neue SQL-Kürzungsangriffe und ihre Vermeidung" von Bala Neerumalla behandelt. Der Artikel ist jedoch nicht mehr online. Die Ausgabe mit diesem Artikel - die Ausgabe vom November 2006 des MSDN Magazine - ist nur als Windows-Hilfedatei (in .chmFormat). Wenn Sie es herunterladen, wird es möglicherweise aufgrund der Standardsicherheitseinstellungen nicht geöffnet. In diesem Fall klicken Sie mit der rechten Maustaste auf die Datei MSDNMagazineNovember2006en-us.chm und wählen Sie "Eigenschaften". In einer dieser Registerkarten gibt es eine Option für "Vertraue diesem Dateityp" (oder so ähnlich), die überprüft / aktiviert werden muss. Klicken Sie auf die Schaltfläche "OK" und versuchen Sie dann erneut, die CHM- Datei zu öffnen .
Eine weitere Variante des Truncation-Angriffs ist die Annahme, dass eine lokale Variable verwendet wird, um den vom Benutzer angegebenen "sicheren" Wert zu speichern, da einzelne Anführungszeichen so verdoppelt wurden, dass sie ausgeblendet werden, um diese lokale Variable aufzufüllen und das einzelne Anführungszeichen zu platzieren Am Ende. Die Idee dabei ist, dass, wenn die lokale Variable nicht die richtige Größe hat, am Ende nicht genügend Platz für das zweite einfache Anführungszeichen vorhanden ist. Lassen Sie die Variable mit einem einfachen Anführungszeichen enden, das dann mit dem einfachen Anführungszeichen kombiniert wird Beendet den Literalwert in Dynamic SQL und wandelt dieses endende einfache Anführungszeichen in ein eingebettetes einfaches Anführungszeichen mit Escapezeichen um. Das Zeichenfolgenliteral in Dynamic SQL endet dann mit dem nächsten einfachen Anführungszeichen, mit dem das nächste Zeichenfolgenliteral beginnen sollte. Beispielsweise:
-- Parameters:
DECLARE @UserID INT = 37,
@NewPassword NVARCHAR(15) = N'Any Value ....''',
@OldPassword NVARCHAR(15) = N';Injected SQL--';
-- Stored Proc:
DECLARE @SQL NVARCHAR(MAX),
@NewPassword_fixed NVARCHAR(15) = REPLACE(@NewPassword, N'''', N''''''),
@OldPassword_fixed NVARCHAR(15) = REPLACE(@OldPassword, N'''', N'''''');
SELECT @NewPassword AS [@NewPassword],
REPLACE(@NewPassword, N'''', N'''''') AS [REPLACE output],
@NewPassword_fixed AS [@NewPassword_fixed];
/*
@NewPassword REPLACE output @NewPassword_fixed
Any Value ....' Any Value ....'' Any Value ....'
*/
SELECT @OldPassword AS [@OldPassword],
REPLACE(@OldPassword, N'''', N'''''') AS [REPLACE output],
@OldPassword_fixed AS [@OldPassword_fixed];
/*
@OldPassword REPLACE output @OldPassword_fixed
;Injected SQL-- ;Injected SQL-- ;Injected SQL--
*/
SET @SQL = N'UPDATE dbo.TableName SET [Password] = N'''
+ @NewPassword_fixed + N''' WHERE [TableNameID] = '
+ CONVERT(NVARCHAR(10), @UserID) + N' AND [Password] = N'''
+ @OldPassword_fixed + N''';';
SELECT @SQL AS [Injected];
Hier ist nun das auszuführende Dynamic SQL:
UPDATE dbo.TableName SET [Password] = N'Any Value ....'' WHERE [TableNameID] = 37 AND [Password] = N';Injected SQL--';
Dasselbe dynamische SQL in einem besser lesbaren Format lautet:
UPDATE dbo.TableName SET [Password] = N'Any Value ....'' WHERE [TableNameID] = 37 AND [Password] = N';
Injected SQL--';
Dies zu beheben ist einfach. Führen Sie einfach einen der folgenden Schritte aus:
- DO NOT USE DYNAMIC SQL WENN NICHT UNBEDINGT ERFORDERLICH! (Ich liste dies zuerst auf, weil es wirklich das erste sein sollte, was zu berücksichtigen ist).
- Ordnungsgemäße Größe der lokalen Variablen (dh sie sollte doppelt so groß sein wie der Eingabeparameter), nur für den Fall, dass alle übergebenen Zeichen einfache Anführungszeichen sind.
Verwenden Sie keine lokale Variable, um den "festen" Wert zu speichern. stecke das einfach REPLACE()
direkt in die Erstellung des Dynamic SQL:
SET @SQL = N'UPDATE dbo.TableName SET [Password] = N'''
+ REPLACE(@NewPassword, N'''', N'''''') + N''' WHERE [TableNameID] = '
+ CONVERT(NVARCHAR(10), @UserID) + N' AND [Password] = N'''
+ REPLACE(@OldPassword, N'''', N'''''') + N''';';
SELECT @SQL AS [No SQL Injection here];
Das Dynamic SQL ist nicht mehr gefährdet:
UPDATE dbo.TableName SET [Password] = N'Any Value ....''' WHERE [TableNameID] = 37 AND [Password] = N';Injected SQL--';
Anmerkungen zum obigen Funktionsbeispiel:
- Ja, das ist ein sehr ausgeklügeltes Beispiel. Es gibt nicht viel, was man mit nur 15 Zeichen tun kann. Sicher, vielleicht
DELETE tableName
um destruktiv zu sein, aber weniger wahrscheinlich, um einen Back-Door-Benutzer hinzuzufügen oder ein Administratorkennwort zu ändern.
- Diese Art von Angriff erfordert wahrscheinlich die Kenntnis des Codes, der Tabellennamen usw. Es ist weniger wahrscheinlich, dass ein zufälliger Fremder / Script-Kiddie sie ausführt, aber ich habe an einem Ort gearbeitet, an dem ein eher verärgerter ehemaliger Mitarbeiter angegriffen wurde, der von einer Sicherheitslücke wusste auf einer bestimmten Webseite, die niemand sonst kannte. Das heißt, manchmal haben Angreifer eine genaue Kenntnis des Systems.
- Sicher, das Zurücksetzen des Kennworts für jeden wird wahrscheinlich untersucht, was das Unternehmen darauf hinweisen kann, dass ein Angriff stattfindet, aber dennoch genügend Zeit bietet, um einen Back-Door-Benutzer einzuschleusen oder sekundäre Informationen für die spätere Verwendung / Nutzung abzurufen.
- Auch wenn dieses Szenario größtenteils akademisch ist (dh in der realen Welt wahrscheinlich nicht vorkommt), ist es immer noch nicht unmöglich.
Ausführlichere Informationen zu SQL Injection (in Bezug auf verschiedene RDBMS und Szenarien) finden Sie im Open Web Application Security Project (OWASP) unter:
Testen auf SQL Injection
Verwandte Antwort auf Stapelüberlauf bei SQL Injection und SQL Truncation:
Wie sicher ist T-SQL, nachdem Sie das Escape-Zeichen ersetzt haben?
EXEC usp_actorBirthdays 'Tom', 'Male''; DROP TABLE tblActor'