Kann die parametrisierte Anweisung die gesamte SQL-Injection stoppen?

79

Wenn ja, warum gibt es immer noch so viele erfolgreiche SQL-Injektionen? Nur weil einige Entwickler zu dumm sind, um parametrisierte Anweisungen zu verwenden?

iceagle
quelle
6
Dies ist eine großartige Frage mit absolut schrecklichen Antworten (wie die Zeit, die ich kommentiere)
Ibu
Ich wünsche mir, dass jemand mit einem guten Ruf von mindestens 15.000 oder mit guter Erfahrung wertvolle Beiträge zu dieser Frage leisten kann.
Ibu
4
Weitere Informationen zu diesem Thema finden Sie in Bill Karwins Sql Injection Myths and Fallacies Talk and Slides . Er erklärt, was SQL-Injection ist, wie Escape normalerweise nicht gut genug ist und wie gespeicherte Prozeduren und parametrisierte Anweisungen kompromittiert werden können.
Mike
2
Sehen Sie sich auch einige Antworten von Bill Karwin auf ähnliche Fragen an: Was ist SQL-Injection?
Mike

Antworten:

64

Die Links, die ich in meinen Kommentaren zur Frage gepostet habe, erklären das Problem sehr gut. Ich habe meine Gefühle darüber, warum das Problem weiterhin besteht, unten zusammengefasst:

  1. Diejenigen, die gerade erst anfangen, haben möglicherweise keine Kenntnis von SQL-Injection.

  2. Einige kennen die SQL-Injection, denken jedoch, dass Escape die (einzige?) Lösung ist. Wenn Sie eine schnelle Google-Suche durchführen php mysql query, wird als erste Seite die Seite angezeigt mysql_query, auf der ein Beispiel für die Interpolation von Escape-Benutzereingaben in eine Abfrage angezeigt wird . Es gibt keine Erwähnung (zumindest nicht, dass ich sehen kann), stattdessen vorbereitete Anweisungen zu verwenden. Wie andere gesagt haben, gibt es so viele Tutorials, die Parameterinterpolation verwenden, dass es nicht wirklich überraschend ist, wie oft sie noch verwendet werden.

  3. Unverständnis darüber, wie parametrisierte Anweisungen funktionieren. Einige denken, dass es nur ein ausgefallenes Mittel ist, um Werten zu entkommen.

  4. Andere kennen parametrisierte Anweisungen, verwenden sie jedoch nicht, weil sie gehört haben, dass sie zu langsam sind. Ich vermute, dass viele Leute gehört haben, wie unglaublich langsam parametrisierte Aussagen sind, aber tatsächlich keine eigenen Tests durchgeführt haben. Wie Bill Karwin in seinem Vortrag betonte, sollte der Leistungsunterschied selten als Faktor herangezogen werden, wenn die Verwendung vorbereiteter Aussagen in Betracht gezogen wird. Die Vorteile der einmaligen Vorbereitung und Ausführung vieler werden häufig vergessen, ebenso wie die Verbesserungen der Sicherheit und der Wartbarkeit des Codes.

  5. Einige verwenden überall parametrisierte Anweisungen, jedoch mit Interpolation von nicht aktivierten Werten wie Tabellen- und Spaltennamen, Schlüsselwörtern und bedingten Operatoren. Beispiele hierfür sind dynamische Suchvorgänge, bei denen Benutzer eine Reihe verschiedener Suchfelder, Vergleichsbedingungen und Sortierreihenfolgen angeben können.

  6. Falsches Sicherheitsgefühl bei Verwendung eines ORM. ORMs ermöglichen weiterhin die Interpolation von SQL-Anweisungsteilen - siehe 5.

  7. Programmierung ist ein großes und komplexes Thema, Datenbankverwaltung ist ein großes und komplexes Thema, Sicherheit ist ein großes und komplexes Thema. Die Entwicklung einer sicheren Datenbankanwendung ist nicht einfach - selbst erfahrene Entwickler können sich überraschen lassen.

  8. Viele der Antworten zum Stackoverflow helfen nicht. Wenn Benutzer Fragen schreiben, die dynamisches SQL und Parameterinterpolation verwenden, fehlen häufig Antworten, die darauf hindeuten, stattdessen parametrisierte Anweisungen zu verwenden. Bei einigen Gelegenheiten wurde mein Vorschlag, vorbereitete Aussagen zu verwenden, von Leuten widerlegt - normalerweise aufgrund des wahrgenommenen inakzeptablen Leistungsaufwands. Ich bezweifle ernsthaft, dass diejenigen, die die meisten dieser Fragen stellen, in der Lage sind, die zusätzlichen Millisekunden, die für die Erstellung einer parametrisierten Aussage benötigt werden, katastrophale Auswirkungen auf ihre Anwendung zu haben.

Mike
quelle
63

Wenn Artikel über parametrisierte Abfragen sprechen, die SQL-Angriffe stoppen, erklären sie nicht wirklich, warum. Oft handelt es sich um "Es tut, also fragen Sie nicht warum" - möglicherweise, weil sie sich selbst nicht kennen. Ein sicheres Zeichen für einen schlechten Erzieher ist eines, das nicht zugeben kann, dass er etwas nicht weiß. Aber ich schweife ab. Wenn ich sage, ich fand es völlig verständlich, verwirrt zu sein, ist das einfach. Stellen Sie sich eine dynamische SQL-Abfrage vor

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

Eine einfache SQL-Injection wäre also, den Benutzernamen als 'OR 1 = 1--' einzugeben. Dies würde die SQL-Abfrage effektiv durchführen:

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

Dies bedeutet, dass Sie alle Kunden auswählen, deren Benutzername leer ('') oder 1 = 1 ist. Dies ist ein Boolescher Wert, der true entspricht. Dann wird - verwendet, um den Rest der Abfrage zu kommentieren. Dies druckt also einfach die gesamte Kundentabelle aus oder macht damit, was Sie wollen. Wenn Sie sich anmelden, wird es mit den Berechtigungen des ersten Benutzers angemeldet, der häufig der Administrator sein kann.

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, dass dies überhaupt nichts ändert. 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 sqlQuery 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 von "Nobody OR 1 = 1 '-" und einem leeren Passwort gesucht, das 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 wie XSS-Angriffe hat, da Sie weiterhin 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.

Josip Ivic
quelle
1
Dies trägt viel zu dem bei, wonach ich gesucht habe, aber können Sie mehr darüber erklären, was Sie für die "Eingabevalidierung" tun würden? Sie haben auch erwähnt, dass mit der Abfrage andere Angriffe stattfinden könnten, z. B. XSS. Können Sie jedoch erklären, wie dies geschehen würde? Wie würden wir uns also im Wesentlichen vollständig vor SQL Injection schützen, oder schauen wir uns alle Arten von Injection an? Vielen Dank.
XaolingBao
3
@JosipIvic: Angesichts der Anzahl der Personen, die gefragt haben, wie parametrisierte Anweisungen funktionieren, ist es schockierend zu sehen, dass so wenige - wenn überhaupt - die Antwort wirklich so aufschlüsseln, wie Sie es getan haben. Vielen Dank, dass Sie eine so klare Erklärung mit einem ziemlich intuitiven Beispiel geschrieben haben.
daOnlyBG
Brillant. Ein Beispiel sagt mehr als tausend Worte!
Drenai
10

Na gute Frage. Die Antwort ist eher stochastisch als deterministisch und ich werde versuchen, meine Ansicht anhand eines kleinen Beispiels zu erklären.

Es gibt viele Referenzen im Internet, die uns empfehlen, Parameter in unseren Abfragen zu verwenden oder gespeicherte Prozeduren mit Parametern zu verwenden, um SQL Injection (SQLi) zu vermeiden. Ich werde Ihnen zeigen, dass gespeicherte Prozeduren (zum Beispiel) nicht der Zauberstab gegen SQLi sind. Die Verantwortung liegt weiterhin beim Programmierer.

Betrachten Sie die folgende gespeicherte SQL Server-Prozedur, mit der die Benutzerzeile aus einer Tabelle 'Benutzer' abgerufen wird:

create procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
declare @sql as nvarchar(512)
set @sql = 'select usrID, usrUName, usrFullName, usrRoleID '+
           'from Users '+
           'where usrUName = '''+@name+''' and usrPass = '''+@pass+''''
execute(@sql)

Sie können die Ergebnisse erhalten, indem Sie den Benutzernamen und das Passwort als Parameter übergeben. Angenommen, das Passwort ist im freien Text (nur zur Vereinfachung dieses Beispiels), wäre ein normaler Anruf:

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [dbo].[getUser] 
   @name = 'admin'
  ,@pass = '!@Th1siSTheP@ssw0rd!!'
GO

Aber hier haben wir eine schlechte Programmiertechnik, die vom Programmierer innerhalb der gespeicherten Prozedur verwendet wird, so dass ein Angreifer Folgendes ausführen kann:

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [TestDB].[dbo].[getUser] 
   @name = 'admin'
  ,@pass = 'any'' OR 1=1 --'
GO

Die obigen Parameter werden als Argumente an die gespeicherte Prozedur übergeben, und der SQL-Befehl, der schließlich ausgeführt wird, lautet:

select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = 'admin' and usrPass = 'any' OR 1=1 --'

..die alle Zeilen von Benutzern zurückbekommt

Das Problem hierbei ist, dass selbst wir dem Prinzip "Erstellen einer gespeicherten Prozedur und Übergeben der Felder zur Suche als Parameter" folgen, das SQLi weiterhin ausgeführt wird. Dies liegt daran, dass wir nur unsere schlechte Programmierpraxis in die gespeicherte Prozedur kopieren. Die Lösung des Problems besteht darin, unsere gespeicherte Prozedur wie folgt umzuschreiben:

alter procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = @name and usrPass = @pass

Ich versuche zu sagen, dass die Entwickler zuerst lernen müssen, was ein SQLi-Angriff ist und wie er ausgeführt werden kann, und dann ihren Code entsprechend schützen müssen. Das blinde Befolgen von "Best Practices" ist nicht immer der sicherere Weg ... und vielleicht haben wir deshalb so viele "Best Practices" -Fehler!

Andreas Venieris
quelle
Ich kann Ihren Standpunkt verstehen und bin daran schuld. Manchmal besteht Bedarf an einer dynamischen SQL-Abfrageerstellung, bei der ich die Verkettung von Parametern verwendet habe. Wie würden Sie vorschlagen, dass ich es mache?
TheProvost
@ TheProvost das ist eine gute Frage. Betrachten Sie sp_executesql: msdn.microsoft.com/en-us/library/ms188001.aspx
Tim
@ Tim Hallo tim. Ich bin neu in Dynamic SQL. Was ist der Unterschied zwischen sp_executesql und EXECUTE (@SqlQuery)
TheProvost
2
Ich denke, dieser Beitrag erklärt ein einfaches Beispiel gut: codeproject.com/Tips/586207/… - aber im Grunde tut EXECUTE (@SqlQuery) nichts, um die SQL-Injektion zu verhindern, jedoch sp_executesql (@SqlQuery, ..., ...) verhindert es. Die Beispiele im Microsoft-Artikel sollten helfen.
Tim
Tim hat die Lösung TheProvost ...;) Sie können sp_executesql (@QUERY, @PARAMETERS, @VARS) ... für einen dynamischen SQL-Fall verwenden ...;)
Andreas Venieris
5

Ja, die Verwendung vorbereiteter Anweisungen stoppt zumindest theoretisch alle SQL-Injektionen. In der Praxis sind parametrisierte Anweisungen möglicherweise keine wirklich vorbereiteten Anweisungen, z. B. PDOin PHP werden sie standardmäßig emuliert, sodass sie für einen Edge-Case-Angriff offen sind .

Wenn Sie wirklich vorbereitete Aussagen verwenden, ist alles sicher. Nun, zumindest solange Sie nicht unsicheres SQL in Ihre Abfrage einbinden, um beispielsweise darauf reagieren zu können, dass Sie keine Tabellennamen vorbereiten können.

Wenn ja, warum gibt es immer noch so viele erfolgreiche SQL-Injektionen? Nur weil einige Entwickler zu dumm sind, um parametrisierte Anweisungen zu verwenden?

Ja, Bildung ist hier der Hauptpunkt und die Basis des Legacy-Codes. Viele Tutorials verwenden Escape und diese können leider nicht einfach aus dem Web entfernt werden.

Kelunik
quelle
1
Die verknüpfte Antwort hat eigentlich nichts mit vorbereiteten Aussagen zu tun.
Ihr
1
@YourCommonSense: Es geht um parametrisierte Abfragen. Sie sind möglicherweise keine tatsächlichen Vorbereitungen, sondern werden je nach verwendetem Treiber emuliert. Es ist wichtig zu wissen und sehr verbunden ...
Kelunik
1
Andere Antworten auf derselben Seite haben einen sehr guten Kommentar: "Wenn ALLE Ihre Abfragen parametrisiert sind, sind Sie auch vor Injektionen 2. Ordnung geschützt. Bei Injektionen 1. Ordnung wird vergessen, dass Benutzerdaten nicht vertrauenswürdig sind. Bei Injektionen 2. Ordnung werden Datenbankdaten vergessen nicht vertrauenswürdig (weil es ursprünglich vom Benutzer kam). "
Rodrigo
@kelunik Bei der verknüpften Antwort geht es auch nicht um parametrisierte Abfragen, sondern um eine Bibliothek, die sie im Wesentlichen fälscht. Eine parametrisierte Abfrage wird mit separaten Parameterwerten an den Server gesendet.
Panagiotis Kanavos
@PanagiotisKanavos: Ich kenne den Inhalt dieser Antwort ziemlich gut. Es ist nur ein Beispiel (und ein ziemlich häufiges), dass die von Ihnen verwendeten parametrisierten Abfragen möglicherweise nicht als vorbereitete Anweisungen implementiert werden ...
Kelunik
3

Ich vermeide absolute Programmierkenntnisse. Es gibt immer eine Ausnahme. Ich empfehle gespeicherte Prozeduren und Befehlsobjekte. Ein Großteil meines Hintergrunds ist SQL Server, aber ich spiele von Zeit zu Zeit mit MySQL. Gespeicherte Prozeduren bieten viele Vorteile, einschließlich zwischengespeicherter Abfragepläne. Ja, dies kann mit Parametern und Inline-SQL erreicht werden, aber das eröffnet mehr Möglichkeiten für Injection-Angriffe und hilft nicht bei der Trennung von Bedenken. Für mich ist es auch viel einfacher, eine Datenbank zu sichern, da meine Anwendungen im Allgemeinen nur Ausführungsberechtigungen für diese gespeicherten Prozeduren haben. Ohne direkten Zugriff auf Tabellen / Ansichten ist es viel schwieriger, etwas zu injizieren. Wenn der Anwendungsbenutzer gefährdet ist, hat er nur die Berechtigung, genau das auszuführen, was vordefiniert wurde.

Meine zwei Cent.

Derek
quelle
Wie hängt das mit der Frage zusammen? Wie werden Sie Parameter aufrufen und an die gespeicherte Prozedur übergeben? Verwenden Sie die Verkettung von Zeichenfolgen oder eine parametrisierte Abfrage? Außerdem - was ist, wenn jemand die Zeichenfolgenverkettung innerhalb der gespeicherten Prozedur verwendet, um eine "dynamische" Abfrage zu erstellen? Nur weil es sich um eine gespeicherte Prozedur handelt, heißt das nicht, dass sie sicherer ist
Panagiotis Kanavos
Im Allgemeinen verwende ich ein Befehlsobjekt und vermeide es auch, "dynamische Abfragen" von Entwurf auszuführen.
Derek
2

Ich würde nicht "dumm" sagen.

Ich denke, die Tutorials sind das Problem. Die meisten SQL-Tutorials, Bücher, was auch immer, erklären SQL mit Inline-Werten, ohne die Bindungsparameter zu erwähnen. Menschen, die aus diesen Tutorials lernen, haben keine Chance, es richtig zu lernen.

Markus Winand
quelle
2
Es ist nicht genug. Warum benutzen die Leute kein Framework oder irgendeinen Orm? Warum testen sie nicht mit einem dummen Tester auf "dumme Injektion"? Weil der Chef Sie manchmal nicht gut bezahlt oder Ihnen X Gelder für ein Projekt zahlt und Sie von einem Projekt zu einem anderen Projekt und von einem zu einem anderen laufen müssen, um etwas Geld zu bekommen. Du musst schneller und schneller sein. Der Codierer ist gestresst und überdruckt, sodass der Code funktioniert, aber schlecht geschrieben ist.
Jedi
2

Da der meiste Code nicht im Hinblick auf Sicherheit und Verwaltung geschrieben wird, wählen sie fast immer die Option, wenn sie zwischen dem Hinzufügen von Funktionen (insbesondere etwas Sichtbarem, das verkauft werden kann) und Sicherheit / Stabilität / Zuverlässigkeit (was viel schwieriger zu verkaufen ist) wählen ehemalige. Sicherheit ist nur dann ein Problem, wenn sie zum Problem wird.

böse otto
quelle
2

Kann die parametrisierte Anweisung die gesamte SQL-Injection stoppen?

Ja, solange Ihr Datenbanktreiber einen Platzhalter für jedes mögliche SQL-Literal bietet . Die meisten vorbereiteten Statement-Treiber tun dies nicht. Angenommen, Sie würden niemals einen Platzhalter für einen Feldnamen oder ein Array von Werten finden. Dadurch kann ein Entwickler mithilfe von Verkettung und manueller Formatierung wieder auf die manuelle Anpassung einer Abfrage zurückgreifen. Mit vorhergesagtem Ergebnis.

Aus diesem Grund habe ich meinen MySQL-Wrapper für PHP erstellt, der die meisten Literale unterstützt, die der Abfrage dynamisch hinzugefügt werden können, einschließlich Arrays und Bezeichner.

Wenn ja, warum gibt es immer noch so viele erfolgreiche SQL-Injektionen? Nur weil einige Entwickler zu dumm sind, um parametrisierte Anweisungen zu verwenden?

Wie Sie sehen, ist es in der Realität einfach unmöglich, alle Ihre Abfragen zu parametrisieren, selbst wenn Sie nicht dumm sind.

Ihr gesunder Menschenverstand
quelle
Wenn ALLE Ihre Abfragen parametrisiert sind (sie stammen aus Benutzerdaten oder aus Ihren Datenbankdaten), scheinen Sie geschützt zu sein, wie im am häufigsten bewerteten
Rodrigo
Ich habe Sie nach Ihrer Meinung gefragt, nur weil Sie vernünftig genug erschienen. Ich denke nicht, dass Ihre Methode die beste sein wird, wenn das, was ich an anderer Stelle gelesen habe, zutrifft. Wie auch immer, ich werde es lieben, wenn Sie "mit regulären Tools können Sie nicht ALLE Ihre Abfragen parametrisieren" verbessern.
Rodrigo
Ich fing an, Ihre Antwort zu lesen, bis ich auf die Idee kam, "SQL-Literale" zu identifizieren. Die Idee schien mir nicht ganz richtig zu sein (es schien übertrieben). Wenn es stimmt, dass parametrisierte Abfragen die Injektion in PHP vermeiden (ich recherchiere noch), besteht mein nächster Schritt darin, Javascript-Injektionen zu vermeiden. Dann werde ich zurückkommen, um Ihre Lösung zu studieren. Außerdem verwende ich Postgres, und vielleicht ist Ihre Lösung MySQL-spezifisch?
Rodrigo
Ok, jetzt lese ich es (wieder) und denke nicht, dass "es einfach unmöglich ist, alle Ihre Abfragen zu parametrisieren" eine Verbesserung ist. Ist es in MySQL unmöglich? Ist es auch in PostgreSQL unmöglich? Warum? Gibt es eine Abfrage außerhalb meines PHP-Skripts? Wo? Ich denke, mit Bezeichner meinen Sie ein reserviertes Wort, das Sie versuchen, aus Ihrem $ _POST-Array zu entfernen? Dies scheint mir nicht der richtige Weg zu sein (intuitiv kann ich mich natürlich irren). Außerdem habe ich das "Hast du jemals versucht, es zu binden?" Nicht verstanden. Was binden?
Rodrigo
Das ist im Web nicht so leicht zu finden, wie ich dachte. Bitte fügen Sie eine Referenz hinzu, wenn Sie können.
Rodrigo
2

Zuerst meine Antwort auf Ihre erste Frage: Ja, soweit ich weiß, sind SQL-Injektionen mit parametrisierten Abfragen nicht mehr möglich. Bei Ihren folgenden Fragen bin ich mir nicht sicher und kann Ihnen nur meine Meinung zu den Gründen mitteilen:

Ich denke, es ist einfacher, die SQL-Abfragezeichenfolge "nur" zu schreiben, indem einige verschiedene Teile (möglicherweise sogar abhängig von einigen logischen Überprüfungen) zusammen mit den einzufügenden Werten verkettet werden. Es wird nur die Abfrage erstellt und ausgeführt. Ein weiterer Vorteil besteht darin, dass Sie die SQL-Abfragezeichenfolge drucken (Echo, Ausgabe oder was auch immer) und diese Zeichenfolge dann für eine manuelle Abfrage an das Datenbankmodul verwenden können.

Wenn Sie mit vorbereiteten Anweisungen arbeiten, haben Sie immer mindestens einen Schritt mehr: Sie müssen Ihre Abfrage erstellen (natürlich einschließlich der Parameter). Sie müssen die Abfrage auf dem Server vorbereiten. Sie müssen die Parameter an die tatsächlichen Werte binden, die Sie möchten für Ihre Abfrage verwenden Sie müssen die Abfrage ausführen.

Das ist etwas mehr Arbeit (und nicht so einfach zu programmieren), insbesondere für einige "schnelle und schmutzige" Jobs, die sich oft als sehr langlebig erweisen ...

Freundliche Grüße,

Box

TomS
quelle
1

Führen Sie die folgenden Schritte aus, um Ihre Anwendung vor SQL-Injection zu schützen:

Schritt 1. Eingabe einschränken. Schritt 2. Verwenden Sie Parameter mit gespeicherten Prozeduren. Schritt 3. Verwenden Sie Parameter mit dynamischem SQL.

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

Fahad Hussain
quelle
8
Gespeicherte Prozeduren allein sind eigentlich keine Hilfe. Es ist möglich, Abfragezeichenfolgen in einer gespeicherten Prozedur dynamisch zu erstellen, genau wie im Clientcode.
Phil Miller
@Fahad Ich könnte # 2 umformulieren als "Verwenden Sie parametrisierte Anweisungen in Abfragen und in gespeicherten Prozeduren." +1 zu Novelocrat's Kommentar, dass die Verwendung gespeicherter Prozeduren ohne Parameter nicht viel bringt.
Matthew
1

Die SQL-Injection ist eine Teilmenge des größeren Problems der Code-Injection, bei der Daten und Code über denselben Kanal bereitgestellt werden und Daten mit Code verwechselt werden. Parametrisierte Abfragen verhindern dies, indem sie die Abfrage unter Verwendung des Kontexts darüber bilden, was Daten und was Code sind.

In bestimmten Fällen reicht dies nicht aus. In vielen DBMS ist es möglich, SQL mit gespeicherten Prozeduren dynamisch auszuführen, wodurch ein SQL-Injection-Fehler auf DBMS-Ebene entsteht. Das Aufrufen einer solchen gespeicherten Prozedur mithilfe parametrisierter Abfragen verhindert nicht, dass die SQL-Injection in der Prozedur ausgenutzt wird. Ein weiteres Beispiel ist in diesem Blogbeitrag zu sehen .

Häufiger verwenden Entwickler die Funktionalität falsch. Normalerweise sieht der Code ungefähr so ​​aus, wenn er richtig gemacht wird:

db.parameterize_query("select foo from bar where baz = '?'", user_input)

Einige Entwickler verketten Zeichenfolgen miteinander und verwenden dann eine parametrisierte Abfrage, bei der die oben genannten Daten- / Codeunterscheidungen, die die gesuchten Sicherheitsgarantien bieten, nicht berücksichtigt werden:

db.parameterize_query("select foo from bar where baz = '" + user_input + "'")

Die korrekte Verwendung parametrisierter Abfragen bietet einen sehr starken, aber nicht undurchdringlichen Schutz vor SQL-Injection-Angriffen.

Daniel Crowley
quelle
1

Selbst wenn vorbereitete Anweisungen im gesamten Code der Webanwendung ordnungsgemäß verwendet werden, können SQL-Injection-Fehler bestehen, wenn Datenbankcode-Komponenten Abfragen aus Benutzereingaben auf unsichere Weise erstellen. Das folgende Beispiel zeigt eine gespeicherte Prozedur, die für die SQL-Injection im Parameter @name anfällig ist:

CREATE PROCEDURE show_current_orders
(@name varchar(400) = NULL)
AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ‘SELECT id_num, searchstring FROM searchorders WHERE ‘ +
‘searchstring = ‘’’ + @name + ‘’’’;
EXEC (@sql)
GO

Selbst wenn die Anwendung den vom Benutzer angegebenen Namenswert auf sichere Weise an die gespeicherte Prozedur übergibt, verkettet die Prozedur dies direkt zu einer dynamischen Abfrage und ist daher anfällig.

Hadid Graphics
quelle