Frage:
Könnte Hashing die SQL-Injection verhindern?
lewis
2016-12-19 21:41:02 UTC
view on stackexchange narkive permalink

Aus einer Laune heraus habe ich kürzlich beschlossen, die erste richtige Website, die ich erstellt habe, auf meinem lokalen Webserver zu veröffentlichen, den ich für die Entwicklung verwende. Ich dachte, es wäre eine großartige Umgebung, um SQL zur Injektion zu verwenden, da ich weiß, dass es Fehler gibt und die Site nur für meine persönliche Entwicklung gedacht war.

Wie auch immer, um auf den Punkt zu kommen, Nach ein paar Versuchen war es am weitesten, dass die Seite einen Fehler mit der Anweisung zurückgab. Ich habe versucht, in ein bestimmtes Testkonto zu gelangen, das ich eingerichtet habe (wenn das Ergebnis mehr als ein Konto zurückgibt, wird ein Fehler ausgegeben, sodass ich nicht damit gerechnet habe, jeden Benutzernamen auszuwählen, bei dem 1 = 1 funktioniert), aber jedes Mal, wenn ich einen bekam Antwort, als hätte ich ein normales, falsches Passwort eingegeben. Ich habe mir den PHP-Code angesehen und festgestellt, dass ich das Kennwort vor der Abfrage gehasht habe, damit der Angriff gehasht wurde, bevor er Schaden anrichten konnte.

Neu in der Web-Sicherheit insgesamt zu sein und zu haben Als ich mich für die Webentwicklung interessierte, fragte ich mich, ob es bei dieser Methode der SQL-Injection -Prävention Schwachstellen gibt, da ich davon ausgehe, dass ich mir nichts überlegt habe. Nur zur Klarstellung, dies ist kein "Look, Leute, ich habe etwas Neues gefunden", da es in der Informationssicherheit viel hellere Funken gibt als ich selbst, der dies wahrscheinlich bereits herausgefunden hätte, aber ich würde es gerne tun wissen, warum dies wahrscheinlich nicht als Sicherheitsmechanismus geeignet ist.

Eine [Antwort] (http://stackoverflow.com/a/36628423/3040381) auf eine entfernte verwandte Frage, die ich heute zuvor gelesen habe, insbesondere "Das Hashing eines Passworts ist das sichere Speichern des PasswortsIhre Datenbank. Die Hash-Funktion gibt Bytes keine besondere Bedeutung, daher ist aus Sicherheitsgründen keine Bereinigung ihrer Eingabe erforderlich. "
Alle gehashten Informationen können nicht angezeigt werden.Am Ende hasst du nur für einige und nicht für andere.Wenn Sie überlegen, eine andere Verschlüsselung zu verwenden, haben Sie das gleiche Problem wie das Ersetzen von 'durch'. Sie hoffen, dass diese Lösung funktioniert, was häufig aufgrund von Sonderfällen, an die Sie nicht gedacht haben, häufig nicht funktioniert.Besser eine konsistente Methode, die sich bewährt hat, nämlich die Abfrage parametrisieren.
Fünf antworten:
Ryan Kelso
2016-12-19 22:08:37 UTC
view on stackexchange narkive permalink

Das Hashing des Benutzerkennworts vor der Eingabe in die Abfrage ist also eine zufällige Sicherheitsfunktion, um die SQL-Injection zu verhindern. Sie können dies jedoch nicht unbedingt mit allen Benutzereingaben tun. Wenn ich einen Kunden anhand seines Namens suche und eine Abfrage wie

  habe, wählen Sie * unter Kunde aus, wobei der Name '% userInput%'  

lautet Wenn ich userInput als Hash-Version von dem, was eingegeben wurde, festlegen würde, würde es nicht richtig funktionieren, selbst wenn Name auch in der Datenbank gehasht wurde, würde es nur für genaue Suchabfragen funktionieren. Wenn ich also einen Kunden mit dem Namen "Sue" hätte und eine Suche nach "sue" eingeben würde, würde das nicht funktionieren. Ich würde auch den Namen der Kunden nicht kennen, wenn meine Suche nicht genau übereinstimmt, was nicht praktikabel ist.

Sie möchten die SQL-Injection verhindern, indem Sie Ihre Abfragen nicht wie oben beschrieben durchführen Sie möchten Eingaben in einer Abfrage verarbeiten und parametrisieren und dabei Dinge wie = s und andere Symbole entfernen, die im Kontext der Eingabe keinen Sinn ergeben. Eine gute Anleitung zum Verhindern der SQL-Injection finden Sie hier.

1. Heutzutage führt jede vernünftig gewartete Abfrage-Engine eine sofortige Parametrisierung durch, was bedeutet, dass Sie keine Desinfektion selbst durchführen müssen.Sie lernen einfach die Parametrisierungssyntax, schreiben Ihre Abfrage auf diese Weise und übergeben die Werte getrennt von der Zeichenfolge, die die Abfrage enthält.Ich denke, es ist irreführend zu sagen, dass Sie diese Eingaben "verarbeiten".2. Beim Desinfizieren von Eingaben werden keine Symbole "entfernt".es * entgeht * ihnen.
> "Wenn ich also einen Kunden mit dem Namen" Sue "hätte und eine Suche nach" sue "eingegeben hätte, würde dies nicht funktionieren" - dies kann tatsächlich funktionieren, wenn der Name vor dem Speichern in DB immer in Kleinbuchstaben konvertiert wird.(aber ich sage nicht, dass es natürlich eine gute Praxis ist)
@Sarge Sicher, das nennt man Normalisierung.Bei einer Abfrage nach "Borsch" würde es jedoch immer noch nicht übereinstimmen - da es gehasht ist, stimmen Sie mit allem oder nichts überein.
Vielen Dank für die Antwort und den Leitfaden auch.Obwohl ich immer noch neugierig bin, warum Methoden der Verschleierung nicht mehr zum Schutz vor SQL-Injection verwendet werden, da dies anscheinend recht gut funktioniert und sogar etwas wie eine Caesars-Chiffre eine recht effektive Verhinderung der SQL-Injection bieten könnte.Natürlich schlage ich nicht vor, dass dies nur als ein einziger Verteidigungspunkt verwendet wird, da dies bei jeder Sicherheitsmethode eine schreckliche Idee zu sein scheint, sondern frage mich, warum es nicht eine so beliebte Präventionsmethode ist, die neben anderen angewendet wird.
@Riking aus entwicklungspolitischer und nicht aus sicherheitstechnischer Sicht würde ich sagen, dass die Konvertierung in Groß- / Kleinschreibung vor dem Hashing das Problem lösen sollte, für Benutzernamen, bei denen die Groß- und Kleinschreibung keine Rolle spielen sollte.
@lewis Der Grund dafür ist, dass Verschleierungstechniken viel, * viel * komplizierter sind, als nur die Methode zu verwenden, die die von Ihnen verwendete API standardmäßig anbietet.Alle Benutzereingaben müssen maskiert werden, unabhängig davon, ob sie in SQL, CSV, HTML oder was auch immer ausgegeben werden.Die Regeln für das Escape-Verfahren unterscheiden sich je nach Ausgabeformat und sind im Allgemeinen ziemlich komplex, um von Grund auf neu zu codieren. Deshalb haben wir sie in einige gängige Bibliotheken gestellt.Verwenden Sie einfach etwas wie `Query q = new Query (" SELECT * FROM customer WHERE name like: name ");q.setParameter ("Name", "%" + Name + "%");q.execute (); `oder was auch immer Ihre API tut.
@jpmc26 Sie haben natürlich völlig Recht. Abfrage-Engines sind der richtige Weg, um mit Datenbankinteraktionen zu arbeiten, da sie eine Menge Sicherheit bieten und die Codekomplexität mit der Datenbankinteraktion insgesamt reduzieren können. In Ihrem zweiten Punkt wieder richtig und ichsollte meine Antwort korrigieren, da das Entkommen die Standardmethode ist, um die Eingabe zu akzeptieren.
@lewis Der Grund, warum uns die Verschleierung nicht wirklich wichtig ist, ist, dass es nicht ganz einfach ist, sowohl die Eingabe als auch die Daten im Back-End zu verschleiern und diese abzugleichen und eine Klartextantwort zurückzugeben (wie im Fall der Suche nach einem Kunden mit dem Namen Sue), während, wenn wir immer den Zeichen entkommen, die zum Erstellen einer SQL-Abfrage im Code verwendet werden können (die Sie als Abfrage-Engines verwenden sollten, wie jpmc26 und Stijn de Witt hervorhoben, da diese dies narrensicher machen und Sie das Rad nicht neu erfinden) das ist schnell und keine Sorge, dass Daten im Backend bei der Rückgabe für die Front neu konvertiert werden.
Bryan Field
2016-12-19 22:16:36 UTC
view on stackexchange narkive permalink

Grundsätzlich ja, wenn Sie eine Hash-Eingabe (dargestellt im Hex- oder Base64-Format) vor der Übergabe an SQL erstellen, kann dies kein effektiver SQLi-Angriffsvektor mehr sein. Das gleiche gilt, wenn Sie die Eingabe parseInt ausführen. Diese unterstützen einfach nicht die Zeichen, die für ein nützliches SQLi benötigt werden. (nämlich um aus der angegebenen Zeichenfolge auszubrechen)

Diese Technik ist in der Praxis nur begrenzt nützlich. Das heißt, es wäre nicht kompatibel mit einigen der bekannten SQL-Funktionen wie LIKE , < , > ,
oder indizierten Gleichheitssuchen ( = und <> unter Verwendung des Index)

Als Randnotiz möchte ich darauf hinweisen, dass Passwort-Hashes wirklich gesalzen werden sollten. Wenn diese Kriterien in Ihrem Beispiel erfüllt wären, würden Sie wahrscheinlich keinen Hash mehr in die SQL-Klausel WHERE aufnehmen.

Das heißt ... wenn Sie einmal Hash haben, können Sie nie mehr zurück.Das Hashing von Benutzereingaben vor dem Speichern würde die Injektion sicherlich auch mit schwachem Code verhindern, aber Sie könnten diesen Ansatz im allgemeinen Fall niemals verwenden, da Sie, abgesehen von Kennwörtern, die vorhandenen Daten nicht wirklich zerstören möchtendie Benutzereingabe an erster Stelle.
"Ich würde darauf hinweisen, dass Passwort-Hashes wirklich gesalzen werden sollten."So ein guter Punkt !!Wenn Sie Salze nicht richtig verwenden, könnten Sie am Ende [das größte Kreuzworträtsel in der Geschichte der Welt erstellen] (https://xkcd.com/1286/) wie Adobe ...
John Deters
2016-12-19 22:19:12 UTC
view on stackexchange narkive permalink

Was Sie (versehentlich) tun, ist Teil der sogenannten "Bereinigung Ihrer Eingabe". Dies sind Schritte, die jede Anwendung unternehmen sollte, um Fehler (und damit Schwachstellen) zu reduzieren.

Eine App sollte dies tun Stellen Sie zunächst sicher, dass die Eingabe die Fähigkeit der App, Daten zu akzeptieren, nicht überlaufen kann. Dies kann bedeuten, dass die Eingabe in der Länge überprüft oder auf andere Weise übergroße Daten abgelehnt werden.

Als nächstes sollte die App die Eingabe nach Möglichkeit anhand einer Whitelist überprüfen, um sicherzustellen, dass keine unerwünschten Eingaben in die Logik gelangen können. In einigen Fällen kann dies bedeuten, dass sichergestellt wird, dass die Eingabe nur gültige alphanumerische Zeichen enthält. Aber manchmal macht eine Whitelist für dieses bestimmte Eingabefeld keinen Sinn, dennoch muss der Entwickler die Injektion verhindern, sodass er eine schwarze Liste enthält. Die schwarze Liste bestätigt, dass die Eingabe keine Symbole enthält, von denen bekannt ist, dass sie die Injektion ermöglichen. Der Nachteil von Blacklists ist, dass sie nur vor dem schützen, was der Entwickler zu blockieren weiß. Ein Beispiel könnte eine schwarze Liste sein, die ein Anführungszeichen stoppt, um eine SQL-Injection zu verhindern. Der Entwickler erkennt jedoch möglicherweise nicht, wenn eine Eingabe über eine verschlüsselte URL erfolgt, dass ein% 27 zu einem Anführungszeichen wird.

Intern sollte die Anwendung defensiv geschrieben werden, um sich vor verschiedenen Formen der Injektion zu schützen. Die Verwendung von parametrisiertem SQL (anstatt eine SQL-Abfrage mithilfe von Verkettung zu erstellen) hilft, die SQL-Injection zu verhindern. Aber viele andere Orte, an denen Benutzereingaben landen, können für verschiedene Arten der Injektion anfällig sein. Verzeichnispfade können betroffen sein, wenn ein Angreifer etwas wie ".. \ .. \ .. \ .. \ .. \ .. \ windows \ cmd.exe" eingibt. XPath-Abfragen können manipuliert werden mit nicht autorisierten Daten. Und JavaScript kann den gesamten Weg durch die Datenbank durchlaufen, um den Browser des Opfers zu manipulieren. Andere Verteidigungsformen umfassen das Nichtaufdecken interner Diagnosefehlermeldungen in der Ausgabe und die Protokollierung, um die Identifizierung potenzieller Angreifer zu erleichtern.

Ihre App hat die Eingabe zunächst an eine Hash-Routine übergeben, die den doppelten Effekt hat, die Daten zu bereinigen und ihre Länge zu begrenzen, bevor sie zum SQL-Schritt gelangen. Beachten Sie jedoch, dass die Eingabe in die Hash-Routine möglicherweise immer noch anfällig für einen Pufferüberlauf ist. Was passiert, wenn ein Angreifer ein Passwort von "aaaa [... 1000-mal wiederholt ...] aaaa_Evil_Injection_Here" eingibt? Ihre App muss das noch erledigen.

Ich bin nicht einverstanden mit Ihrer Konzentration auf Desinfektion.So etwas führt dazu, dass Herr O'Doherty seinen Namen nicht in ein Webformular eingeben kann (und nein: Odoherty und ODoherty sind beide * falsch *).Meiner Ansicht nach besteht der richtige Ansatz darin, sicherzustellen, dass Sie nicht vertrauenswürdigen Daten nicht vertrauen - während der gesamten Lebensdauer der Daten (daher sollte das Javascript nicht so in die Ausgabewebseite aufgenommen werden, wie es ausgeführt wird
@MartinBonner, Ich stimme zu, dass Whitelisting und Blacklisting bei weitem nicht so gut sind wie das Schreiben von qualitativ hochwertigem Code, der die Eingabe akzeptieren kann, ohne einen Injektionsangriff zu riskieren.Aufgrund der Komplexität vieler Entwicklungsgeschäfte (Auftragnehmer-Team A schreibt die GUI, anderes Auftragnehmer-Team B schreibt den App-Server, Auftragnehmer-Team C schreibt die Regel-Engine usw.) variiert die Qualität der zugrunde liegenden Ebenen.Manchmal verhindert die defensive Codierung auf einer höheren Ebene, dass eine auf einer niedrigeren Ebene vorhandene Sicherheitsanfälligkeit ausgenutzt wird.
Deprimierend denke ich, dass Sie vielleicht Recht haben.:-(
Ich stimme Martin zu ... überprüfe meinen Namen ... rate mal, wie oft ich Nachrichten wie "Nachname enthält illegale Zeichen" gesehen habe?Tatsache ist, dass die Durchführung der Hygiene selbst sehr schwierig, sehr fehleranfällig und normalerweise falsch ist.Sie möchten einen Benutzer nicht daran hindern, ein Leerzeichen oder ein Anführungszeichen einzugeben. Sie möchten lediglich sicherstellen, dass diese Symbole nicht mit den Regeln des Ausgabeformats in Konflikt geraten.Der beste Weg, um damit umzugehen, besteht in der Tat darin, zu wissen, dass Benutzerdaten (einschließlich aller in der Datenbank gespeicherten Daten) nicht sicher sind, und den für dieses Format vorhandenen Escape-Mechanismus zu verwenden.
Ich bin mit "Bereinigen Ihrer Eingabe" nicht einverstanden - obwohl die Daten eine Eingabe in das System sind, handelt es sich um AUSGABEN aus der Anwendungsebene (wo die SQL-Injection erfolgt).
Your Common Sense
2016-12-20 17:33:11 UTC
view on stackexchange narkive permalink

Wie viele andere Lernende verwechseln Sie den Speicher und den Transport . Und um Letzteres zu schützen, verwöhnen Sie Ersteres absichtlich.

Sie müssen verstehen, dass SQL-Injection aus einem bestimmten Grund nicht als "Datenbank-Injection" bezeichnet wird. Sie müssen die Datenbank, den Speicher nicht schützen. Alles, was Sie schützen müssen, ist der Transport - die SQL-Abfrage. Während Ihr Speicher in der Lage sein sollte, die Daten wie sie sind zu speichern, hat sie überhaupt keinen Wert. Wenn Sie noch einen Beweis für diese Aussage benötigen,

  • kann es verschiedene Kunden geben, die keine Ahnung von Ihrem selbst gebrauten "Schutz"
  • a Die Datenbank wird nicht nur zum Speichern, sondern auch zum Bearbeiten Ihrer Daten verwendet. Versuchen Sie schließlich, Ihre gehashten Benutzernamen
  • zu bestellen. Manchmal müssen Sie die Daten aus einer Datenbank zurückdrucken.

Sie können also feststellen, dass jede Schutzmaßnahme, die die gespeicherten Daten in irgendeiner Weise verändert, einfach falsch ist. Und Ihre Idee ist einfach nicht gut durchdacht.

Joshua
2016-12-20 08:26:14 UTC
view on stackexchange narkive permalink

Hashing schützt die SQL-Injection des Kennwortfelds durch den Schritt, der seine Binärausgabe zurück in eine Zeichenfolge codiert.

Dieser Schutz ist normalerweise nutzlos, reicht jedoch aus, wenn die folgenden Annahmen zutreffen:

  • Ihre Anwendung verarbeitet nur Zeichenfolgen außer Benutzername und Kennwort.
  • Sie entfernen den Benutzernamen aus den Zeichen ' und \ .

Wenn eine dieser Aussagen nicht zutrifft oder jemals in der Zukunft liegt, ist Hashing keine nützliche Verteidigung. Dadurch werden 99,9% der Webanwendungen eliminiert.



Diese Fragen und Antworten wurden automatisch aus der englischen Sprache übersetzt.Der ursprüngliche Inhalt ist auf stackexchange verfügbar. Wir danken ihm für die cc by-sa 3.0-Lizenz, unter der er vertrieben wird.
Loading...