it-swarm.com.de

Wie können die Auswirkungen von SQL-Injection für vorhandene Websites begrenzt und das Risiko verringert werden?

Unsere Website basiert zu 100% auf APIs (mit einem SPA-Client). Kürzlich hat es ein Hacker geschafft, das Passwort unseres Administrators (mit SHA-256 gehasht) durch SQL-Injection (und Cracking PwD) wie folgt zu erhalten:

https://example.com/api/products?userId=3645&type=sqlinject here

Es ist nur ein Beispiel, aber es ist tödlich für uns. Zum Glück war es ein netter Hacker und er hat uns nur eine E-Mail über den Hack geschickt. Glück für eine Website unter Konstantenangriffen während ihres 5-jährigen Bestehens.

Ja, wir wissen, dass wir die Benutzereingaben überall überprüfen und die Anweisung formatieren/maskieren/vorbereiten müssen, bevor wir Daten an MySQL senden. Wir wissen, und wir reparieren es. Wir haben jedoch nicht genügend Entwickler/Tester, um die Sicherheit zu 100% zu gewährleisten.

Angenommen, wir haben eine Wahrscheinlichkeit von 0,1%, dass SQL irgendwie injiziert wird. Wie machen wir es Hackern schwerer, es zu finden und den Schaden so gering wie möglich zu halten?

Was wir bisher tun, um schnelle Lösungen/zusätzliche Messungen durchzuführen:

  1. Am von allen APIs gemeinsam genutzten "Gate" -Ausgang senden wir die unformatierte PDOException und Nachricht nicht mehr wie zuvor. Wir müssen dem Client jedoch noch mitteilen, dass eine Ausnahme aufgetreten ist:

    {type: exception, code: err643, message: 'contact support for err643'}
    

    Ich bin mir bewusst, dass Hacker, die eine Ausnahme sehen, es weiter versuchen werden ...

  2. Der Benutzer PHP verwendet, um eine Verbindung zu MySQL herzustellen, kann nur CRUD zu Tabellen. Ist das sicher genug?

  3. Benennen Sie alle Tabellen um (wir verwenden Open Source, damit Hacker den Tabellennamen erraten können).

Was sollen wir noch tun?

Update: Da es viele Kommentare gibt, möchte ich einige Nebeninformationen geben

  1. Zuallererst ist dies die LEGACY-App, die von einigen studentischen Leuten entwickelt wurde, nicht für Unternehmen. Das Entwicklerteam ist nirgends zu finden, jetzt nur noch 1-2 Hybrid-Entwickler, die Hunderte von Datenzugriffsklassen bearbeiten.
  2. Das Passwort ist Hash mit SHA-256, ja, es ist scheiße. Und wir ändern es auf den empfohlenen PHP-Weg.
  3. SQL Injection ist 17 Jahre alt. Warum gibt es sie noch?
  4. Sind vorbereitete Anweisungen 100% sicher gegen SQL-Injection?
34
Phung D. An

Verbringen Sie nicht viel Zeit mit Problemumgehungen oder halben Korrekturen. Jede Minute, die Sie damit verbringen, die hier vorgeschlagenen Vorschläge zu implementieren, ist eine Minute, die Sie mit der Implementierung vorbereiteter Anweisungen hätten verbringen können. Das ist die einzig wahre Lösung.

Wenn Sie eine SQLi-Sicherheitslücke haben, wird der Angreifer wahrscheinlich am Ende gewinnen, egal was Sie tun, um sie zu verlangsamen. Beachten Sie also, dass Sie zwar Verbesserungen vornehmen können, aber am Ende ein verlorenes Spiel spielen, es sei denn, Sie beheben die Hauptursache des Problems.

Was Sie bisher versucht haben: Das Ausblenden von Fehlermeldungen ist ein guter Anfang. Ich würde Ihnen empfehlen, noch strengere Berechtigungen anzuwenden (siehe unten). Es ist fraglich, ob das Ändern von Tabellennamen hilft , aber wahrscheinlich wird es nicht schaden.

Ok, was ist mit diesen Berechtigungen? Beschränken Sie die Möglichkeiten des Datenbankbenutzers so weit wie möglich auf Tabellen- oder sogar Spaltenebene. Sie können sogar mehrere Datenbankbenutzer erstellen, um die Dinge noch mehr zu sperren. Verwenden Sie beispielsweise nur einen Datenbankbenutzer mit Schreibberechtigung, wenn Sie tatsächlich schreiben. Stellen Sie nur dann eine Verbindung mit einem Benutzer her, der das Recht hat, die Kennwortspalte zu lesen, wenn Sie die Kennwortspalte tatsächlich lesen müssen. Auf diese Weise kann eine Injection-Schwachstelle in einer anderen Abfrage nicht genutzt werden, um Kennwörter zu verlieren.

Eine weitere Option ist die Verwendung einer WAF (Web Application Firewall), z. B. mod_security für Apache. Sie können es so konfigurieren, dass Anforderungen blockiert werden, die verdächtig aussehen. Kein WAF ist jedoch perfekt. Die Konfiguration erfordert Zeit und Energie. Sie sollten diese Zeit wahrscheinlich besser nutzen, um vorbereitete Anweisungen zu implementieren.

Lassen Sie sich auch hier nicht von irgendetwas in ein falsches Sicherheitsgefühl locken. Es gibt keinen Ersatz für die Behebung der Grundursache des Problems.

80
Anders

Der einzig richtige Weg ist die Verwendung vorbereiteter Anweisungen.

  1. Wenn Sie Fehlermeldungen verschleiern, ist dies etwas schwieriger, hält Angreifer jedoch nicht auf.
  2. Sie können die Rechte einschränken, aber alle dem Benutzer gewährten Rechte können vom Angreifer erworben werden. In einigen Fällen ist es auch möglich, Shell-Befehle über eine SQL-Injection auszuführen.
  3. Das Umbenennen von Tabellen hilft Ihnen nicht weiter. Das Tool sqlmap erzwingt die Tabellennamen für Sie char für char. Das braucht nicht viel Zeit.

Sie können auch die Anzahl der Anrufe einschränken, um es Angreifern zu erschweren oder Warnungen bei verdächtigen Anrufen zu erstellen und dieses Handbuch zu beenden. Die einzig richtige Methode zur Behebung dieses Problems ist jedoch die Verwendung vorbereiteter Anweisungen. Durchsuchen Sie einfach Ihren Quellcode und werfen Sie einen Blick auf SQL-Anweisungen mit dynamischem Inhalt und ersetzen Sie diese.

65
trietend

Wir wissen, aber wir haben nicht genug Entwickler/Tester, um es 100% sicher zu machen.

Dies ist das eigentliche Problem. Solange Sie nicht mehr Mitarbeiter einstellen oder Prioritäten neu zuweisen, sind Sie nicht sicher. Das Stoppen von 99,9% der Angreifer bedeutet, dass Ihre Daten kompromittiert wurden. Pflasterlösungen sind eine schlechte Sache, und sie nicht funktionieren. Verschwenden Sie keine Zeit damit, Ihr SQL-Zugriffsmuster zu überarbeiten, während Sie möglicherweise tatsächliche Probleme beheben.

Was die Codelösung betrifft, ist die Verwendung vorbereiteter Anweisungen, wie viele hier vorschlagen, der einfachste Weg, SQL sicher zu verwenden.

Es ist viel einfacher als zu versuchen, die Argumente mit PHP selbst zu bereinigen, und kostet viel weniger Zeit. Durchsuchen Sie einfach Ihre gesamte Codebasis nach allem, was mit SQL zu tun hat, und beheben Sie das Problem.

25
Gloweye

Löschen Sie alle SQL-Dateien für immer aus Ihrem Code

Die beste Lösung für dieses Problem besteht darin, den gesamten SQL-Code als Literalzeichenfolgen aus Ihrem Code zu löschen und ihn nie wieder einzuführen. Verwenden Sie stattdessen ORM Software wie Hibernate oder Entity Framework. Diese Software ist ohnehin viel besser zu verwenden als Raw SQL und parametrisiert Ihr SQL automatisch, wenn es schließlich in die Datenbank gelangt. Wenn es Ihnen möglich ist, haben Sie diese Richtlinie.

Wenn Sie nicht die Zeit haben, diese Pakete zu lernen und zu implementieren, oder sie aus einem anderen Grund nicht verwenden können, ist die Antwort von trietend die nächstbeste, indem Sie vorbereitete Anweisungen verwenden. Auf diese Weise können Sie sich vor SQL-Injection schützen. Das heißt, bis Sie Druck auf Ihre Entwickler ausüben, schnelle Lösungen zu liefern. Zu diesem Zeitpunkt vergessen sie möglicherweise erneut, eine einzelne Variable zu parametrisieren, sodass Sie wieder dort sind, wo Sie begonnen haben.

Wir wissen, aber wir haben nicht genug Entwickler/Tester, um es 100% sicher zu machen.

Es ist nicht ganz klar, was Sie mit dieser Aussage meinen, da vorbereitete Aussagen in jeder gängigen Web-Sprache (PHP, Python, Java, node.js usw.) trivial sind und mehr oder weniger eine 100% ige wirksame Maßnahme gegen SQL-Injection darstellen .

Meinen Sie damit, dass Sie die Entwicklung an Subunternehmer vergeben und es sich nicht leisten können, den Code, den sie für Sie im Vertrag schreiben, einer Qualitätssicherung zu unterziehen? Sie können es sich nicht leisten, dies nicht zu tun: Sie sind hier immer noch die verantwortliche Partei.

Meinen Sie damit, dass Ihre Entwickler zu beschäftigt sind, Funktionen zu implementieren, um einige Stunden für die Aktualisierung der Codebasis zu benötigen? Alles andere als vorbereitete Anweisungen dauert länger und kostet mehr (z. B. ORM, Verschleierung, feinkörnige Berechtigungen usw.).

Meinen Sie damit, dass Ihre Entwickler nicht kompetent genug sind, um diese einfache Aufgabe auszuführen? Das ist ein viel größeres Problem (oder genauer gesagt, SQL-Injection sollte zu diesem Zeitpunkt nicht Ihr größtes Problem sein).

Meinen Sie damit, dass Ihre Codebasis eine solche Schrotflinten-formatierte Spaghetti-Logik aus verschachtelten includes ist, dass selbst kompetente Entwickler ewig brauchen werden, um eine ansonsten einfache Aufgabe von wenigen Stunden auszuführen? Ebenso größeres Problem.

Was auch immer es ist, die Lösung besteht darin, vorbereitete Aussagen zu verwenden, etwa gestern.

9
Jared Smith

Sobald der erste Ratschlag für "vorbereitete Anweisungen" implementiert wurde, würde ich empfehlen, etwas über SQL-Injection zu lesen. Die Frage "Wie verhindere ich die SQL-Injection?" Ist eine ziemlich breite Frage! Sicherheit ist ein Thema, mit dem Sie (und nicht Ihr gesamtes Entwicklerteam) vertraut sein müssen, um das Risiko von Kompromissen zu verringern. Ein Loch untergräbt alle anderen Anstrengungen.

Besuchen Sie das Open Web Application Security Project (OWASP) hier: https://www.owasp.org/index.php/SQL_Injection

Insbesondere das Zusatzmaterial:

  • SQL Injection Prevention Cheat Sheet
  • Cheat Sheet zur Abfrageparametrisierung
  • Leitfaden zum Vermeiden von Sicherheitsanfälligkeiten in SQL Injection

Und auch

  • Überprüfen von Code auf Sicherheitsanfälligkeiten in SQL Injection .
5
Nicolas

Eine Notlösung wäre die Untersuchung einer Webanwendungs-Firewall (WAF). Es gibt einige Unternehmen, die dies als Service anbieten, und einige Cloud-Anbieter, die ebenfalls Angebote anbieten. CloudFlare scheint einen anzubieten, ich habe Incapsula von einem Client verwenden lassen, und ich weiß, dass das AWS WAF-Angebot einige verwaltete Regelsätze für die SQL-Injection enthält.

Dies funktioniert so, dass der gesamte Datenverkehr an/über die WAF gesendet wird (entweder indem er auf Servern eingeschlossen wird oder indem DNS so eingestellt wird, dass er wie bei einem CDN auf die WAF verweist), und nach Dingen gesucht wird, die wie SQL-Injection-Versuche aussehen Die Parameter. Es fängt nicht alle Angriffe ab und blockiert möglicherweise legitimen Datenverkehr, ist jedoch ein verfügbarer Bandaid-Fix.

4
CoderTao

Mit "nicht genügend Entwickler" meine ich, dass einige einflussreiche Personen in Ihrem Unternehmen der Meinung sind, dass es höhere Prioritäten gibt. Alle Ressourcen, die Sie haben, werden für diese Dinge verwendet. Wenn Sie also Ihr Sicherheitsproblem beheben, verlieren Sie in einer Kosten-Nutzen-Analyse an anderen Dingen.

Ihre Aufgabe hier ist es, ihre Meinung zu ändern und das Update zu implementieren. Quantifizieren Sie, worum es geht - was wäre der Geld- und Reputationsschaden eines weiteren Verstoßes? In Ihrem Land gibt es möglicherweise Gesetze, nach denen Sie Kompromisse bei den Daten Ihres Benutzers melden müssen. Wäre das peinlich? Könnte es Medienberichte über die schlechten Praktiken Ihrer Organisation geben?

Stellen Sie sich die Investition zur Sicherung der Sicherheit als Versicherung vor. Wenn Sie im Nachhinein wissen, dass Ihr Gebäude zehn Jahre lang nicht niedergebrannt ist, könnten Sie argumentieren, dass Ihre Prämien eine Verschwendung waren. Aber Sie und Ihre Organisation zahlen für Versicherungen, weil Sie vor einer ungewissen Zukunft stehen. Es ist Risikomanagement.

Das Risiko hat zwei Faktoren: Wahrscheinlichkeit und Auswirkung. Die Wahrscheinlichkeit eines weiteren Verstoßes ist hoch - Sie wissen, dass dies mindestens einmal möglich ist und wurde. Wenn die möglichen Folgen ebenfalls schlimm sind, sollten Sie die Priorität der Behebung Ihrer Sicherheitslücken erhöhen.

2
Concrete Gannet

Wie jeder erwähnt hat, korrigieren Sie den Code auf der Website.

Sie können beliebige Patches an einer Wand anbringen, aber bis die Wand korrekt aufgebaut ist, sind alle Patches ein Pflaster gegen Blutungsprobleme.

Jeder andere Vorschlag, Code zu bereinigen, würde Linus Torvalds als Masterbation bezeichnen.

  • Korrigieren Sie Ihren Code (von den offensichtlichsten Injektionspunkten bis zum letzten I.E Get params) und verwenden Sie vorbereitete Anweisungen. wie kann ich SQL Injection in PHP verhindern

    • Sie können ein [~ # ~] waf [~ # ~] (IE ModSecurity ) vorübergehend ausprobieren, bis Sie dazu in der Lage sind um Dinge zu reparieren.

    • Versuchen Sie vielleicht eine Art IP-Verbot für "Personen, die die Site testen" oder das Blockieren unsicherer Abfragen.

    • Wenn Sie die Möglichkeit haben, einen temporären (sicheren) Anmeldebildschirm vor sich zu erstellen, bis dies behoben ist.

    • Versuchen Sie es mit einem Drittanbieter-Service, bis dies behoben ist, z. B. durch Cloudflare oder was auch immer.

PDOs sind seit PHP 5.1 veröffentlicht am 24. November 2005 ... verfügbar). Entwickler müssen verstehen, dass sie Konsequenzen für ihre schlechten Codierungsgewohnheiten haben, und ich persönlich denke, dass die Qualität zur Rechenschaft gezogen werden sollte der geleisteten Arbeit.

Auf jeden Fall sind PDOs einfach zu implementieren. Wenn Ihre Entwickler keine bessere Qualität liefern können, würde ich eine Bereinigung vorschlagen ...

1
Qndel

Zusätzlich zu all den bisher guten Antworten können Sie Ihre Datenbank so umgestalten, dass die Kennwörter in einer separaten Tabelle mit strengen Zugriffsrechten gespeichert werden, ähnlich wie bei dem spezifischen Problem des Extrahierens von Benutzeranmeldeinformationen die Art und Weise, wie Unix-Systeme sie in/etc/shadow ablegen.

Um Anmeldeinformationen zu überprüfen, benötigen Sie eine gespeicherte Prozedur, die das eingegebene Kennwort (oder den eingegebenen Hash) als Parameter verwendet und einen Booleschen Wert zurückgibt. Mit anderen Worten, Sie verlagern die Aufgabe der Überprüfung von Anmeldeinformationen in die Datenbank, und der tatsächliche Hash verlässt die Datenbank nie.

Dies erfordert nur ein minimales Refactoring und löst Ihr unmittelbares Problem im Stammverzeichnis anstelle einer bestimmten SQL-Injection, während Sie für das nächste anfällig sind.

0
Tom

Die wichtigste Regel ist:

Verwenden Sie Bibliotheken, Tools und APIs, die die sichere Option zur einfachsten Option machen.

Nacht sagt "benutze einfach ein ORM", was eine Teilmenge dieser Regel ist.

Vorbereitete Anweisungen verstoßen gegen diese Regel, da ihre Verwendung umständlich ist und zu einem Aufblähen des Codes führt. Abhängig von Ihrer Datenbank können sie auch langsamer sein als nicht vorbereitete Anweisungen. Sie sind eine gültige Lösung, ich werde niemanden kritisieren, der sie verwendet, aber sie sind nicht unbedingt die beste und bequemste Lösung.

Und ... wir möchten, dass die sichere Option einfach und bequem ist, damit der Programmierer sie aus Eigennutz und Faulheit verwendet. Wir möchten, dass der Programmierer wirklich alles unternimmt, um die unsichere Option zu nutzen! ...

Eine viel bessere Lösung ist eine API wie Python dbapi. Ich habe vor Jahren ein PHP-Äquivalent geschrieben, das wie folgt aussah:

db_query( "SELECT * FROM mytable WHERE id=%s", $id )

Dies ist bequemer als vorbereitete Aussagen. Nur eine Zeile zum Tippen. Außerdem wird das Ergebnis in einer Form zurückgegeben, die foreach () verwenden kann, sodass es viel einfacher zu verwenden ist als fetch () und so weiter. Noch wichtiger ist, dass der hinter dieser API verborgene Code das Escape-Verfahren ordnungsgemäß handhabt. Dies macht SQL-Injektionen irrelevant. Dies behandelt ungefähr 99% der Abfragen, wenn Sie kein ORM verwenden. Dynamische Abfragen (normalerweise Suche) erfordern zwar eine spezielle Behandlung, sind aber dennoch einfach.

Wenn Sie diese Regel beachten, müssen Sie sich irgendwann fragen, warum Sie htmlspecialchars () verwenden müssen und warum die Sprache keine Funktion hat, die die sichere Einstellung (dh keine XSS-Vulns) ermöglicht am einfachsten zu bedienen? Warum Oh warum? Und dann lassen Sie PHP fallen.

0
peufeu