Wie verhindert SQLParameter SQL Injection?

Antworten:

78

Grundsätzlich werden bei einer SQLCommandVerwendung SQLParametersdie Parameter niemals direkt in die Anweisung eingefügt. Stattdessen wird eine aufgerufene Systemprozedur sp_executesqlaufgerufen und die SQL-Zeichenfolge und das Array von Parametern angegeben.

Bei Verwendung als solche werden die Parameter isoliert und als Daten behandelt, anstatt aus der Anweisung analysiert zu werden (und sie möglicherweise zu ändern), sodass das, was die Parameter enthalten, niemals "ausgeführt" werden kann. Sie erhalten nur einen großen Fettfehler, dass der Parameterwert in irgendeiner Weise ungültig ist.

KeithS
quelle
1
Sie erhalten auch eine Fehlermeldung, wenn Sie versuchen, Variablen an Stellen zu verwenden, an denen SQL (und in diesem Fall TSQL) keine Variablen unterstützt. IE: FROMKlausel, ein einzelner Parameter zur Darstellung einer durch Kommas getrennten Liste in einer INKlausel usw.
OMG Ponies
1
Ich denke nicht, dass dies die Frage beantwortet. Sie können eine gespeicherte Prozedur mit der SQLParameter-Klasse aufrufen, die Parameter an die Prozedur übergibt, sp_executesql jedoch nicht aufruft. Was passiert mit den Parameterwerten in einer verketteten SQL-Zeichenfolge?
Ian
57

Eine leichter verständliche und allgemeinere Antwort lautet wie folgt:

Stellen Sie sich eine dynamische SQL-Abfrage vor:

sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password

Eine einfache SQL-Injection wäre nur, den Benutzernamen als einzugeben ' OR 1=1--

Dies würde effektiv die SQL-Abfrage machen:

sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password

Dies bedeutet, dass Sie alle Kunden auswählen, deren Benutzername leer ist ( '') oder 1=1, was ein Boolescher Wert ist, gleich true ist. Anschließend --wird der Rest der Abfrage auskommentiert. Auf diese Weise wird die gesamte Kundentabelle ausgedruckt oder Sie können damit tun, was Sie wollen.

Jetzt machen es parametrisierte Abfragen anders, mit Code wie:

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?' parameters.add("User", username) parameters.add("Pass", password)

Dabei sind Benutzername und Passwort Variablen, die auf den zugehörigen eingegebenen Benutzernamen und das Passwort verweisen.

An diesem Punkt, denken Sie vielleicht, ändert dies überhaupt nichts. Sicherlich könnten Sie immer noch so etwas wie Nobody OR 1 = 1 'in das Feld für den Benutzernamen eingeben - und so die Abfrage effektiv durchführen:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'

Und dies scheint ein gültiges Argument zu sein. Aber du würdest dich irren.

Parametrisierte Abfragen funktionieren so, dass die SQL-Abfrage als Abfrage gesendet wird und die Datenbank genau weiß, was diese Abfrage bewirkt. Erst dann werden der Benutzername und die Kennwörter lediglich als Werte eingefügt. Dies bedeutet, dass sie die Abfrage nicht beeinflussen können, da die Datenbank bereits weiß, was die Abfrage tun wird. In diesem Fall würde also nach einem Benutzernamen Nobody OR 1=1'--und einem leeren Passwort gesucht, was falsch sein sollte.

Dies ist jedoch keine vollständige Lösung, und die Eingabevalidierung muss noch durchgeführt werden, da dies keine Auswirkungen auf andere Probleme hat, z Angriffe, da Sie immer noch Javascript in die Datenbank einfügen könnten. Wenn dies dann auf einer Seite ausgelesen wird, wird es abhängig von einer Ausgabevalidierung als normales Javascript angezeigt. Das Beste ist also, weiterhin die Eingabevalidierung zu verwenden, aber parametrisierte Abfragen oder gespeicherte Prozeduren zu verwenden, um SQL-Angriffe zu stoppen.

Quelle: http://www.lavamunky.com/2011/11/why-parameterized-queries-stop-sql.html

anaik
quelle
10

"Parametersammlungen wie SqlParameterCollection bieten Typprüfung und Längenüberprüfung. Wenn Sie eine Parametersammlung verwenden, wird die Eingabe als Literalwert behandelt, und SQL Server behandelt sie nicht als ausführbaren Code. Ein zusätzlicher Vorteil der Verwendung einer Parametersammlung besteht darin, dass Sie kann Typ- und Längenprüfungen erzwingen. Werte außerhalb des Bereichs lösen eine Ausnahme aus. Dies ist ein gutes Beispiel für eine Tiefenverteidigung. "

http://msdn.microsoft.com/en-us/library/ff648339.aspx

Dave Brace
quelle
5

Bei Verwendung parametrisierter Abfragen wird die Angriffsfläche auf das Herumspielen mit den Parametern reduziert.

Verwenden Sie SqlParameters, aber vergessen Sie nicht Überlauf, Unterlauf und nicht validierte Parameter. Wenn die Methode beispielsweise "proc buy_book (@price money)" lautet, versucht ein böswilliger Angreifer, die Anwendung dazu zu bringen, mit @priceset to ausgeführt zu werden 0.01, oder versucht, die Anwendung dazu zu bringen, etwas Interessantes zu tun, indem er etwas sendet, das einen Überlauf verursacht. SQL-Überläufe sind in der Regel nicht interessant (dh sie verursachen nur Ausnahmen, es ist unwahrscheinlich, dass Sie in den benachbarten Speicher schreiben können).

MatthewMartin
quelle