In Bezug auf die SQL-Injection verstehe ich die Notwendigkeit, einen string
Parameter zu parametrisieren, vollständig . Das ist einer der ältesten Tricks im Buch. Aber wann kann es gerechtfertigt sein, eine nicht zu parametrisieren SqlCommand
? Werden Datentypen als "sicher" angesehen, um nicht parametrisiert zu werden?
Zum Beispiel: Ich habe mich nicht überall betrachte in der Nähe von einem Experten in SQL, aber ich kann die Fälle nicht denken , wo es potenziell anfällig für SQL - Injection wäre ein zu akzeptieren bool
oder ein int
und verketten es nur nach rechts in die Abfrage.
Ist meine Annahme richtig oder könnte dies möglicherweise eine große Sicherheitslücke in meinem Programm hinterlassen?
Zur Verdeutlichung ist diese Frage markiert c #das ist eine stark typisierte Sprache; Wenn ich "Parameter" sage, denke ich an etwas wie public int Query(int id)
.
quelle
Antworten:
Ich denke, es ist sicher ... technisch gesehen , aber es ist eine schreckliche Angewohnheit, sich darauf einzulassen. Möchten Sie wirklich solche Abfragen schreiben?
Sie sind auch in Situationen anfällig, in denen sich ein Typ von einer Ganzzahl in eine Zeichenfolge ändert (denken Sie an die Mitarbeiternummer, die trotz ihres Namens möglicherweise Buchstaben enthält).
Wir haben den Typ der EmployeeNumber von
int
in geändertstring
, aber vergessen, unsere SQL-Abfragen zu aktualisieren. Hoppla.quelle
AddWithValue
? blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…AddWithValue
sei denn, Sie haben eine Zuordnung von Datenbanktypen als Teil des dynamischen Aufbaus der Anweisung. Ich würde annehmen, dass Sie eine Liste von Zielspalten haben und als Teil des Wörterbuchs die Typen haben könnten, wenn Sie möchten. Ansonsten nimm einfach den Performance-Hit. Letztendlich ist es nur eine gute Information zu wissen, denke ich.AddWithValue
?" sollte wirklich sein "wenn Sie den Typ kennen, dann sollten Sie auf die Verwendung verzichtenAddWithValue
.Wenn eine stark typisierte Plattform auf einem Computer mit Ihnen (wie ein Web - Server) zu steuern, können Sie Code - Injektion für Abfragen mit nur verhindern
bool
,DateTime
oderint
(und anderen numerischen) Werten. Was Anlass zur Sorge gibt, sind Leistungsprobleme, die dadurch verursacht werden, dass SQL Server gezwungen wird, jede Abfrage neu zu kompilieren, und verhindert wird, dass gute Statistiken darüber abgerufen werden, welche Abfragen mit welcher Häufigkeit ausgeführt werden (was die Cache-Verwaltung beeinträchtigt).Dieser Teil "Auf einem Computer, den Sie steuern" ist jedoch wichtig, da ein Benutzer andernfalls das Verhalten des Systems zum Generieren von Zeichenfolgen aus diesen Werten ändern kann, um beliebigen Text einzuschließen.
Ich denke auch gerne langfristig. Was passiert, wenn die heutige altmodische, stark typisierte Codebasis über die automatische Übersetzung in die dynamische Sprache der neuen Aktualität portiert wird und Sie plötzlich die Typprüfung verlieren, aber noch nicht die richtigen Komponententests für den dynamischen Code haben? ?
Es gibt wirklich keinen guten Grund, keine Abfrageparameter für diese Werte zu verwenden. Es ist der richtige Weg, dies zu tun. Gehen Sie voran und codieren Sie Werte fest in die SQL-Zeichenfolge, wenn sie wirklich Konstanten sind. Andernfalls sollten Sie einen Parameter verwenden. Es ist nicht so, als wäre es schwer.
Letztendlich würde ich dies nicht per se als Fehler bezeichnen , aber ich würde es als Geruch bezeichnen : etwas, das für sich genommen nur knapp unter einem Fehler liegt, aber ein starkes Indiz dafür ist, dass Fehler in der Nähe sind oder irgendwann auftreten werden. Guter Code vermeidet es, Gerüche zu hinterlassen, und jedes gute statische Analysewerkzeug weist darauf hin.
Ich werde hinzufügen, dass dies leider nicht die Art von Argument ist, die Sie direkt gewinnen können. Es klingt nach einer Situation, in der es nicht mehr ausreicht, "richtig" zu sein, und wenn Sie Ihren Mitarbeitern auf die Zehen treten, um dieses Problem selbst zu beheben, wird dies wahrscheinlich keine gute Teamdynamik fördern. es könnte letztendlich mehr weh tun als es hilft. Ein besserer Ansatz in diesem Fall könnte darin bestehen, die Verwendung eines statischen Analysewerkzeugs zu fördern. Dies würde den Bemühungen, die darauf abzielen und zurückgehen und vorhandenen Code reparieren, Legitimität und Glaubwürdigkeit verleihen.
quelle
DateTime
oderint
In einigen Fällen ist es möglich, einen SQL-Injection-Angriff mit anderen nicht parametrisierten (verketteten) Variablen als Zeichenfolgenwerten durchzuführen - siehe diesen Artikel von Jon: http://codeblog.jonskeet.uk/2014/08/08/the-bobbytables -Kultur / .
Beim Aufrufen
ToString
kann ein benutzerdefinierter Kulturanbieter einen Nicht-String-Parameter in seine String-Darstellung umwandeln, wodurch SQL in die Abfrage eingefügt wird.quelle
int
s möglich sein ?"CultureInfo
schwierig zu wissen, warum Sie ohnehin eine SQL-Injektion benötigen würden.Dies ist selbst für Nicht-String-Typen nicht sicher. Verwenden Sie immer Parameter. Zeitraum.
Betrachten Sie folgendes Codebeispiel:
Auf den ersten Blick sieht Code sicher aus, aber alles ändert sich, wenn Sie einige Änderungen in den regionalen Windows-Einstellungen vornehmen und die Injektion im Kurzdatumsformat hinzufügen:
Der resultierende Befehlstext sieht nun folgendermaßen aus:
Dies gilt auch für den
int
Typ, da der Benutzer ein benutzerdefiniertes negatives Vorzeichen definieren kann, das leicht in SQL Injection geändert werden kann.Man könnte argumentieren, dass eine invariante Kultur anstelle der aktuellen Kultur verwendet werden sollte, aber ich habe so oft Zeichenfolgenverkettungen gesehen, und es ist ziemlich leicht zu übersehen, wenn Zeichenfolgen mit Objekten verkettet werden
+
.quelle
int
Typ gesagt haben ?"SELECT * FROM Table1 WHERE Id =" + intVariable.ToString ()
Sicherheit
Es ist in Ordnung.
Angreifer können nichts in Ihre eingegebene int-Variable einfügen.
Leistung
nicht OK.
Es ist besser, Parameter zu verwenden, daher wird die Abfrage einmal kompiliert und für die nächste Verwendung zwischengespeichert. Das nächste Mal wird die Abfrage auch bei unterschiedlichen Parameterwerten zwischengespeichert und muss nicht auf dem Datenbankserver kompiliert werden.
Codierungsstil
Schlechte Praxis.
"SELECT * FROM Product WHERE Id =" + TextBox1.Text
Es ist zwar nicht Ihre Frage, aber vielleicht nützlich für zukünftige Leser:
Sicherheitskatastrophe
!
Selbst wenn das
Id
Feld eine Ganzzahl ist, kann Ihre Abfrage SQL Injection unterliegen. Angenommen, Sie haben eine Abfrage in Ihrer Anwendung"SELECT * FROM Table1 WHERE Id=" + TextBox1.Text
. Ein Angreifer kann sie in ein Textfeld einfügen.1; DELETE Table1
Die Abfrage lautet:Wenn Sie hier keine parametrisierte Abfrage verwenden möchten, sollten Sie typisierte Werte verwenden:
Ihre Frage
Ich denke, das Ändern dieser Codes ist keine Zeitverschwendung. In der Tat wird eine Änderung empfohlen!
Wenn Ihr Mitarbeiter int-Variablen verwendet, besteht kein Sicherheitsrisiko. Ich denke jedoch, dass das Ändern dieser Codes keine Zeitverschwendung ist und dass das Ändern dieser Codes empfohlen wird. Es macht Code lesbarer, wartbarer und beschleunigt die Ausführung.
quelle
.ToString()
wird durch ein Betriebssystemkonfigurationselement bestimmt, das leicht geändert werden kann, um beliebigen Text einzuschließen.Es gibt tatsächlich zwei Fragen in einer. Und die Frage aus dem Titel hat sehr wenig mit Bedenken zu tun, die das OP in den nachfolgenden Kommentaren geäußert hat.
Obwohl mir klar ist, dass es für das OP auf den jeweiligen Fall ankommt, ist es für die Leser von Google wichtig, die allgemeinere Frage zu beantworten, die wie folgt formuliert werden kann: "Ist die Verkettung so sicher wie vorbereitete Aussagen, wenn ich mich vergewissere?" dass jedes Literal, das ich verkette, sicher ist? ". Ich möchte mich also auf Letzteres konzentrieren. Und die Antwort ist
Auf jeden Fall NEIN.
Die Erklärung ist nicht so direkt, wie die meisten Leser es gerne hätten, aber ich werde mein Bestes geben.
Ich habe eine Weile darüber nachgedacht, was zu dem Artikel führte (obwohl er auf der PHP-Umgebung basiert), in dem ich versuchte, alles zusammenzufassen. Mir ist der Gedanke gekommen, dass die Frage des Schutzes vor SQL-Injection häufig in Bezug auf einige verwandte, aber engere Themen wie das Entweichen von Zeichenfolgen, das Casting von Typen und dergleichen nicht berücksichtigt wird. Obwohl einige der Maßnahmen für sich genommen als sicher angesehen werden können, gibt es weder ein System noch eine einfache Regel, die befolgt werden muss. Das macht es sehr rutschig und belastet die Aufmerksamkeit und Erfahrung des Entwicklers zu sehr.
Die Frage der SQL-Injection kann nicht auf ein bestimmtes Syntaxproblem vereinfacht werden. Es ist breiter als der durchschnittliche Entwickler gedacht. Es ist auch eine methodische Frage. Es ist nicht nur "Welche bestimmte Formatierung müssen wir anwenden", sondern auch " Wie es gemacht werden muss".
(Unter diesem Gesichtspunkt ist ein Artikel von Jon Skeet, der in der anderen Antwort zitiert wird, eher schlecht als gut, da er sich wieder auf einen Randfall konzentriert, sich auf ein bestimmtes Syntaxproblem konzentriert und das Problem überhaupt nicht anspricht.)
Wenn Sie versuchen, die Frage des Schutzes nicht als Ganzes, sondern als eine Reihe verschiedener Syntaxprobleme zu behandeln, stehen Sie vor einer Vielzahl von Problemen.
Im Gegensatz zu diesem Durcheinander sind vorbereitete Aussagen in der Tat der Heilige Gral:
(Als ich weiter nachdachte, stellte ich fest, dass der aktuelle Satz von Platzhaltern nicht für die Anforderungen des realen Lebens ausreicht und erweitert werden muss, sowohl für die komplexen Datenstrukturen wie Arrays als auch für SQL-Schlüsselwörter oder -Kennungen, die manchmal zu den hinzugefügt werden müssen Abfrage auch dynamisch, aber ein Entwickler bleibt für einen solchen Fall unbewaffnet und muss auf die Verkettung von Zeichenfolgen zurückgreifen, aber das ist eine andere Frage.
Interessanterweise wird die Kontroverse dieser Frage durch die sehr kontroverse Natur des Stapelüberlaufs provoziert. Die Idee der Website besteht darin, bestimmte Fragen von Benutzern zu verwenden, die direkt nachfragen , um das Ziel einer Datenbank mit allgemeinen Antworten zu erreichen, die für Benutzer geeignet sind, die aus der Suche stammen . Die Idee ist nicht schlecht , per se , aber es funktioniert nicht in einer Situation wie dieser: wenn ein Benutzer eine fragt sehr engen Frage , vor allem in einem Streit um ein Argument zu bekommen mit einem Kollegen (oder zu entscheiden , ob es sich lohnt , den Code zu Refactoring). Während die meisten erfahrenen Teilnehmer versuchen, eine Antwort zu schreiben, denken Sie an die Mission of Stack Overflow insgesamt, was ihre Antwort für so viele Leser wie möglich gut macht, nicht nur für das OP.
quelle
Denken wir nicht nur an Sicherheitsaspekte oder typsichere Überlegungen.
Der Grund, warum Sie parametrisierte Abfragen verwenden, besteht darin, die Leistung auf Datenbankebene zu verbessern. Aus Datenbanksicht ist eine parametrisierte Abfrage eine Abfrage im SQL-Puffer (um die Terminologie von Oracle zu verwenden, obwohl ich mir vorstelle, dass alle Datenbanken intern ein ähnliches Konzept haben). Die Datenbank kann also eine bestimmte Anzahl von Abfragen im Speicher speichern, die vorbereitet und zur Ausführung bereit sind. Diese Abfragen müssen nicht analysiert werden und sind schneller. Häufig ausgeführte Abfragen befinden sich normalerweise im Puffer und müssen nicht jedes Mal analysiert werden, wenn sie verwendet werden.
ES SEI DENN
Jemand verwendet keine parametrisierten Abfragen. In diesem Fall wird der Puffer kontinuierlich durch einen Strom nahezu identischer Abfragen geleert, von denen jede analysiert und von der Datenbank-Engine ausgeführt werden muss. Die Leistung leidet insgesamt, da selbst häufig ausgeführte Abfragen häufig mehrmals analysiert werden Tag. Ich habe Datenbanken für meinen Lebensunterhalt optimiert und dies war eine der größten Quellen für niedrig hängende Früchte.
JETZT
Um Ihre Frage zu beantworten: Wenn Ihre Abfrage eine kleine Anzahl unterschiedlicher numerischer Werte aufweist, verursachen Sie wahrscheinlich keine Probleme und können die Leistung tatsächlich unendlich verbessern. Wenn jedoch möglicherweise Hunderte von Werten vorhanden sind und die Abfrage häufig aufgerufen wird, wirkt sich dies auf die Leistung Ihres Systems aus. Tun Sie dies also nicht.
Ja, Sie können den SQL-Puffer erhöhen, aber dies geht letztendlich immer zu Lasten anderer kritischerer Speicheranwendungen wie dem Zwischenspeichern von Indizes oder Daten. Moralisch, verwenden Sie parametrisierte Abfragen ziemlich religiös, damit Sie Ihre Datenbank optimieren und mehr Serverspeicher für die wichtigen Dinge verwenden können ...
quelle
So fügen Sie der Maciek-Antwort einige Informationen hinzu:
Es ist einfach, die Kulturinformationen einer .NET-Drittanbieter-App zu ändern, indem Sie die Hauptfunktion der Assembly durch Reflektion aufrufen:
Dies funktioniert nur, wenn die Hauptfunktion von BobbysApp öffentlich ist. Wenn Main nicht öffentlich ist, können Sie andere öffentliche Funktionen aufrufen.
quelle
Wenn Sie meiner Meinung nach garantieren können, dass der Parameter, mit dem Sie arbeiten, niemals eine Zeichenfolge enthält, ist dies sicher, aber ich würde es auf keinen Fall tun. Außerdem wird ein leichter Leistungsabfall festgestellt, da Sie eine Verkettung durchführen. Die Frage, die ich Ihnen stellen würde, ist, warum Sie keine Parameter verwenden möchten.
quelle
Es ist in Ordnung, aber niemals sicher. Und die Sicherheit hängt immer von den Eingaben ab. Wenn das Eingabeobjekt beispielsweise TextBox ist, können die Angreifer etwas Kniffliges tun, da das Textfeld Zeichenfolgen akzeptieren kann. Sie müssen also eine Art Validierung / Konvertierung durchführen um verhindern zu können, dass Benutzer falsche Eingaben machen. Aber die Sache ist, es ist nicht sicher. So einfach ist das.
quelle
Nein, auf diese Weise können Sie einen SQL-Injection-Angriff erhalten. Ich habe einen alten Artikel auf Türkisch geschrieben, der zeigt, wie hier . Artikelbeispiel in PHP und MySQL, aber das Konzept funktioniert in C # und SQL Server gleich.
Grundsätzlich greift man folgendermaßen an. Nehmen wir an, Sie haben eine Seite, auf der Informationen nach dem Wert der Ganzzahl-ID angezeigt werden. Sie haben diesen Wert nicht wie unten angegeben parametrisiert.
Okay, ich gehe davon aus, dass Sie MySQL verwenden und ich greife folgendermaßen an.
Beachten Sie, dass der hier injizierte Wert keine Zeichenfolge ist. Wir ändern den Zeichenwert mithilfe der ASCII-Funktion in int. Sie können dasselbe in SQL Server mit "CAST (YourVarcharCol AS INT)" erreichen.
Danach benutze ich Längen- und Teilzeichenfolgenfunktionen, um nach Ihrem Datenbanknamen zu suchen.
Wenn Sie dann den Datenbanknamen verwenden, beginnen Sie, Tabellennamen in der Datenbank abzurufen.
Natürlich müssen Sie diesen Prozess automatisieren, da Sie nur EIN Zeichen pro Abfrage erhalten. Sie können es jedoch problemlos automatisieren. Mein Artikel zeigt ein Beispiel in Watir . Verwenden Sie nur eine Seite und keinen parametrisierten ID-Wert. Ich kann jeden Tabellennamen in Ihrer Datenbank lernen. Danach kann ich nach wichtigen Tabellen suchen. Es wird einige Zeit dauern, aber es ist machbar.
quelle
public void QuerySomething(int id) { // this will only accept an integer }
Nun ... eines ist sicher: Sicherheit ist NICHT in Ordnung, wenn Sie eine (vom Benutzer verwendete) Zeichenfolge mit Ihrer SQL-Befehlszeichenfolge verketten. Es spielt keine Rolle, wann immer die where-Klausel auf eine Ganzzahl oder einen beliebigen Typ verweist. Injektionen können auftreten.
Was bei SQL Injection wichtig ist, ist der Datentyp der Variablen, mit der der Wert vom Benutzer abgerufen wurde.
Angenommen, wir haben eine Ganzzahl in der where-Klausel und:
Die Benutzervariable ist eine Zeichenfolge. Dann ok, es ist nicht sehr einfach zu injizieren (mit UNION), aber es ist sehr einfach, mit 'OR 1 = 1' zu umgehen - wie Angriffe ...
Wenn die Benutzervariable eine Ganzzahl ist. Andererseits können wir die Stärke des Systems "testen", indem wir ungewöhnlich große Zahlen auf Systemabstürze oder sogar auf einen versteckten Pufferüberlauf (auf der letzten Zeichenfolge) testen ...;)
Möglicherweise sind die Parameter für Abfragen oder (noch besser - imo) für gespeicherte Prozeduren nicht 100% sicher, aber sie sind die am wenigsten erforderliche Maßnahme (oder die elementare, wenn Sie dies bevorzugen), um sie zu minimieren.
quelle