Brute-force - /DoS-Prävention in PHP
Ich versuche ein Skript schreiben, um zu verhindern, dass brute-force-login-versuche in eine website, die ich Baue. Die Logik geht ungefähr so:
- Benutzer sendet login-Daten.
- Überprüfen Sie, ob Benutzername und Passwort korrekt ist
- Wenn ja, lassen Sie Sie in.
- Wenn Nein, notieren Sie ein misslungener Versuch in der Datenbank. Überprüfen Sie, ob es zu viele nicht innerhalb einer bestimmten Frist (zB: 5 in 5 Minuten):
- Wenn ja, dann pause Ausführung für 10 Sekunden:
sleep(10)
, dann melden login failure an den Benutzer. - Bericht einen login failure an den Benutzer sofort
- Wenn ja, dann pause Ausführung für 10 Sekunden:
Erklären dieses zu einem co-worker, ich wurde gefragt, wie dies helfen würde, wenn ein hacker gesendet, sagen wir, 1000 Anfragen in der Sekunde. Würde die ersten 5 würden sofort zurückkehren, und dann die restlichen 995 alle nehmen nur 10 Sekunden?
Ich habe den leisen Verdacht, dass ich nicht vollständig verstehen, wie HTTP funktioniert - ist, dass die situation oben noch möglich, oder gibt es eine Begrenzung für die Anzahl der gleichzeitigen Anfragen, die ein server handhaben kann von einem client?
Würde eine bessere Lösung sein, um eine Erhöhung der Schlafzeit?
sleep($numRequestsInLast5Minutes - 5)
Also die ersten 5 wäre schnell, und dann alle nachfolgenden steigern würde schlafen.
- Statt der Einführung einer schlafen, warum nicht die Einführung eines captcha nach einer maximal zulässigen fehlgeschlagenen login-versuche?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das problem ist die balance zwischen der Verfügbarkeit für die Benutzer und Angreifer-Modell.
Erste Lösung
Benutzer: könnte blockiert werden, und Sie mögen es nicht zurücksetzen
Angreifer: blockiert alle Benutzer, indem Sie versuchen, zu authentifizieren, für alle Benutzer (vor allem, wenn alle Anmeldungen sind öffentlich verfügbar)
Zweite Lösung
Die Frage ist: was ist der Wert von 'amount_of_time' ?
Benutzer: kann lästig sein, zu warten, amount_of_time " für jeden Fehler
Angreifer: weiter versuchen, mit niedrigeren test /Sekunden
Dritte Lösung
Benutzer: weniger ärgerlich für einige Passwort-Fehler
Angreifer: Sperrung der Benutzer das herstellen einer Verbindung durch das senden viel Falsches Passwort
Vierte Lösung
Benutzer: müssen lösen das CAPTCHA (nicht zu Komplex)
Angreifer: müssen lösen das CAPTCHA (muss Komplex sein)
Gute Lösung (und durch eine Menge von Websites), aber seien Sie vorsichtig, um unsere CAPTCHA. Umsetzung. Trotzdem gibt es einen trick (siehe nächste Lösung).
Fünfte Lösung
Benutzer: Benutzer kann gesperrt sein, weil er sich nicht richtig erinnern, sein Passwort an.
Angreifer: versuchen Sie das gleiche Kennwort mit unterschiedlichen Benutzer, da die Blockierung basiert auf der Anzahl der login durch den Benutzer.
Endgültige Lösung ?
Benutzer: User nicht die IP gesperrt, sondern müssen daran denken, Ihr Passwort an.
Angreifer: schwierig, um eine effiziente brute-force-Angriff.
Die wichtigen Hinweise
Ist das login-Formular oder die login-submit link, der ist gesperrt ? Sperrung des login-Formulars ist nutzlos.
Resistenz gegen brute-force ist ZUNÄCHST ein problem der Passwort-Komplexität, so müssen Sie eine strenge Passwort-policy (insbesondere im Fall von verteilten brute-force).
Ich nicht schweigen von der Tatsache hash Ihre Passwörter mit Salz, Sie machen schon das richtige ? Denn wenn es einfacher ist, den Zugriff auf die Kennwort-Datenbank als brute-forcing, der Angreifer wird diese Lösung wählen ("Eine Kette ist nur so stark wie Ihr schwächstes Glied").
Ich würde vorschlagen, wenn der Benutzer vergeblich versucht hat, sagen, mehr als fünf mal und fünf Minuten, Sie beginnen Rückkehr eine
503 Service Unavailable
sofort, für diese IP-Adresse. Wenn ein login fehlschlägt, könnten Sie mit memcache, um die aktuelle schlechte versuche, für die eine IP, und dann erhöhen Sie die Menge und speichern Sie es zurück zu memcache mit einem 5-minütigen Ablauf.Sie nicht möchten, um eine
sleep
in Ihrem PHP-code, wie, die es ermöglicht eine single-user-erstellen Sie viele verbindungen zu Ihrem web-server und möglicherweise bringen andere Benutzer.Da der Benutzer noch nicht angemeldet, Sie verfügen nicht über ein session cookie, und wenn der Benutzer versucht, den brute-force Ihren Weg in ein Konto, können Sie nicht ein cookie.
Benutzt habe ich etwas in dieser Art...
Überprüfen Sie Benutzername und Kennwort
1.1 Wenn keine übereinstimmung dann, aufzeichnen letzten fehlgeschlagenen login-Zeit für die combo und die Anzahl der fehlgeschlagenen logins.
1.2 Jedes scheitern macht die Wartezeit zwischen Anmeldung etwas wie failsCount * 30 Sekunden bis zu einem maximum (etwa 10 Minuten).
Ich entwickelt habe, diese aber nicht freigegeben, es in der wildnis noch, so dass jegliches feedback wäre sehr geschätzt.
if (timeNow - timeFailed) > 3600
dann Zähler zurücksetzen.Machte ich eine Klasse, die kümmert sich um brute-force-Angriff-Schutz in PHP.
https://github.com/ejfrancis/BruteForceBlocker
protokolliert alle fehlgeschlagenen logins die ganze site in eine db-Tabelle, und wenn die Anzahl der fehlgeschlagenen logins in den letzten 10 Minuten (oder welcher Zeitrahmen Sie wählen) ist über eine bestimmte Grenze, es erzwingt eine Zeitverzögerung und/oder ein captcha-Anforderung, bevor Sie sich einloggen wieder.
Beispiel:
Ich bin nicht sicher, was die beste Praxis ist, aber beim Umgang mit DoS-Angriffen, eine bessere Strategie ist eigentlich umleiten Verkehr Weg von Ihrem server. Einstellung der timeouts nicht wirklich helfen, weil du bist immer noch der, der die Anfrage verarbeitet und PHP.
Haben Sie als Einrichtung einen anderen web-server läuft ein einfacher abgespeckte version Ihres login-Seite? Wenn der Benutzer versucht, zu viele Male (z.B., Tausende Male), eine Nachricht senden, konfigurieren Sie Ihren router und leiten Sie diese Benutzer zu der zweiten web-server.
Es ist, wie wenn Webseiten get hit mit dem slashdot-Effekt, viele von Ihnen nur umleiten von Datenverkehr entfernt, bis der Verkehr reduziert wird.