Login Sicherheit PHP?

5 Antworten

Es gehört noch weitaus mehr dazu, ein Login sicher zu machen. Unter Umständen kann man durchaus eine Woche lang oder länger daran entwickeln, bevor man sich überhaupt um andere Dinge kümmern kann, da es ein zentraler sicherheitskritischer Bereich einer Website ist. Zunächst möchte ich auf deine Ideen eingehen.

1. Überprüfung ob der Computer also IP momentan für die Authentifizierung gesperrt ist, wenn ja Meldung anzeigen, sonst: 2. HTML Login Form zeigen

Ein Angreifer darf auf keinen Fall wissen, dass seine IP gesperrt ist. Zeige ihm ganz normal das Login-Formular an wie jedem anderen Nutzer auch, aber weise ihn beim Absenden immer darauf hin, dass Benutzername und/oder Passwort inkorrekt sind. Der Hinweis, dass die IP aufgrund zu vieler fehlgeschlagener Loginversuche gesperrt ist, sollte dagegen auf der Seite platziert werden, auf der der Nutzer sein Passwort zurücksetzen kann. Dort sollte dem Nutzer mitgeteilt werden, dass er womöglich nur gesperrt ist und zunächst abwarten sollte. Dies schränkt die Arbeit für Bots wesentlich ein.

3. wenn Daten via Post kommen werden diese zuerst durch eine Funktion gejagt, die Schadcode entfernt, dann gelangen sie erst in die Login Funktion, welche dann die Daten mit den in der Datenbank hingelegten prüft.

Beachte dabei unbedingt, dass du folgende Attacken ausschließt:

  • XSS (am besten durch htmlentities)
  • SQL-Injections (am besten durch Prepared Statements)
  • CSRF (am besten durch einen Token)
  • Einige weitere Attacken
wenn die eingeben Daten  nicht richtig sindwird geprüft, wie oft in der letzten Stunde falsche Anmeldedaten eingegeben worden sind, wenn dies mehr als 10 mal der Fall war wird bis zum nächsten Tag die IP vom Login gesperrt.

Siehe dazu noch weitere Ideen: https://stackoverflow.com/questions/1727329/brute-force-dos-prevention-in-php

wenn die eingegeben Daten richtig sind wird ein Token erzeugt der in der PHP Session gesichert wird.

Achte darauf, dass die Session immer in einem Cookie gespeichert wird und niemals in der URL.

Außerdem wird ein Datensatz generiert in dem der Token zusammen mit der IP und Benutzer-ID gespeichert wird.

Speichere noch mehr Dinge in der Session UND in einem Cookie (damit Session, Cookie und vom Browser gelieferte Informationen, also drei Werte, übereinstimmen müssen). Bringe z.B. auch Informationen wie den User Agent und weitere Unbekannte mit ins Spiel und hashe alles zu einem String, den du speicherst und zusätzlich zur Session-ID und User-ID vergleichst.

Außerdem gibt es noch einige weitere Aspekte, die ich ansprechen möchte.

  • Richte deinen Server sicher ein (Betriebssystem, PHP-Einstellungen, Webserver-Einstellungen etc.).
  • Übertrage Daten nur über eine TLS-Verbindung. Das Zertifikat sollte unter keinen Umständen selbst erstellt sein, sondern von einer allgemein anerkannten CA stammen. So bietet z.B. Let's Encrypt kostenlose Zertifikate an.
  • Verwende nur lange, verschiedene und zufällig generierte Passwörter für dein OS, den Webserver, Datenbanken etc., schließe nicht gebrauchte Ports
  • Verwende auf keinen Fall den Root-Benutzer für die Datenbank, sondern lege mehrere Nutzer mit unterschiedlichen Rechten an, z.B. einen Nutzer, der nur Eintragen kann, einen der nur lesen kann etc. Ein Nutzer sollte auch keinen Zugriff auf mehrere Tabellen haben.
  • Speichere inkludierte PHP-Scripte außerhalb des Document-Roots, damit diese von außen nicht aufgerufen werden können
  • Verschlüssele das Passwort nicht, sondern hashe es. Nutze dafür keine unsicheren Algorithmen wie MD5 oder SHA1, sondern z.B. bcrypt. Verwende die Funktion password_hash. Nutze PASSWORD_DEFAULT, damit, sollte ein sicherer Algorithmus gefunden werden, automatisch umgestellt wird. Damit es dabei nicht zu Problemen kommt, überprüfe immer mit password_needs_rehash, damit immer jeder Nutzer auf dem neuesten technischen Stand ist. Beachte außerdem, dass dein Server gegen DDoS-Attacken abgesichert sein sollte.
  • Blockiere nicht nur die IP, sondern unter Umständen auch das Konto selbst und sende eine Mail an den Nutzer, über die dieser die Blockierung aufheben kann.
  • Bevor diese Blockierung stattfindet, zeige ein CAPTCHA an. Setze dabei nicht auf ein heutzutage unsichereres textbasiertes CAPTCHA, sondern z.B. auf reCAPTCHA.
  • Lasse das action-Attribut eines Formulars nicht leer, sondern setze es auf $_SERVER['PHP_SELF'], um einen ClickJacking-Angriff zu verhindern. Filtere dabei unbedingt diese Variable, damit ein XSS-Angriff vermieden werden kann. Setze außerdem den X-Frame-Options-Header, damit die Einbindung des Login-Scripts nicht möglich ist.
  • Validiere bei der Registrierung immer alle Usereingaben genau auf Richtigkeit, z.B. durch Filter, und nutze eine Registrierungsmail.
  • Schütze dein System vor Session-Hijacking, indem du z.B. Sessions bei jedem Seitenaufruf regenerierst. Schau dir auch diesen und diesen Thread sowie diese Seite an.
  • Recherchiere nach weiteren Attacken, die du bei einem Login verhindern musst

Das ist erst einmal alles, was mir dazu einfällt. Solltest du dazu Fragen haben, kannst du dich gerne per Kommentar melden.

3

Soweit alles verständlich, aber wieso das mit dem Action Feld?

0
35
@justrie
Soweit alles verständlich, aber wieso das mit dem Action Feld?

Das bezieht sich wiederum auf die Einbindung in iframes. Dadurch kann der CSRF-Schutz umgangen werden, was hier gut beschrieben wird.

0
38

Ungefähr 90% der üblichen Passwörter befinden sich in den Top Zehntausend von gängigen Passwortlisten.

Würde ich bei einem Login diese 10000 Passwörter durchprobieren, würde mich dein Ansatz nach 3 Versuchen blocken.

Allerdings nehme ich für solche Dinge immer einige zehntausend Rechner, sodass pro IP / Host nur ein einziger Versuch gezählt wird. Das gute an dieser Methode ist, dass sie auch massiv parallel funktioniert und man in wenigen Sekunden alle 10000 Passwörter durchprobiert hat, ohne dabei geblockt zu werden ... wie gesagt, mit 90%er Erfolgswahrscheinlichkeit.

(Disclaimer: Bevor jetzt ein Mitleser die Stirn runzelt ... ich mache das beruflich ganz legal mit Kundenauftrag als Teil eines regulären Pentestings, also nichts Kriminelles!)

Deshalb ist eine Zeitbasierte Loginblockade wertvoller, als eine hostbasierte. Wobei man die 10000 häufigsten Passwörter mit etwas Geduld auch bei nur 3 Versuchen pro Minute relativ (!) schnell durch hat. Vor allem wenn man in diesem Tempo wieder 10000 Accounts mit 10000 parallelen Verbindungen von 10000 verschiedenen Hosts angreift ... da kannst du sicher sein, dass dir schon beim ersten Versuch einige zich User-Accounts in die Hände fallen.

Deshalb achte beim Bau deiner Loginformulare bitte auch darauf, dass du auch a) Angreifer mit massiven Ressourcen und b) mit viiieeeel Geduld effektiv blockierst!

Ansonsten ist alles sehr vorbildlich, was du so schreibst! ;)

1
38

Nachtrag: Neben IP, Token bzw. Session-ID, usw. ist es auch sehr schick, eine Art Fingerprinting zu nutzen.

Das ist nach deutschem Recht aber teilweise verboten bzw. - wenn man Glück hat - in Teilen eine Grauzone, aber wenn der Server im Ausland steht, bzw. der Kunde im Ausland sitzt, könnte man darüber nachdenken.

Das funktioniert sogar schon recht passabel ganz ohne JavaScript. Die ganzen "Accept-XYZ" Header allein sind oft schon recht einzigartig und als Fallback sollte man zumindest diese nutzen. Außerdem kann man - mit etwas mehr Aufwand - prüfen ob und wie Pipelining / Prefetching / Caching usw. vom Client genutzt wird ... aber das bleibt der Fantasie des Serverbetreibers überlassen. :)

Aber wie gesagt: Bitte nicht in Deutschland! Sonst gibt es u. U. eine Abmahnung von der Konkurrenz!

Alle Angaben ohne Gewähr! :)

1
1. Überprüfung ob der Computer also IP momentan für die Authentifizierung gesperrt ist, wenn ja Meldung anzeigen, sonst:

Einen Nutzer über seine IP zu sperren ist trivial, da die meisten Router heutzutage Ihre IP Adresse entweder täglich, wöchentlich oder monatlich je nach Konfiguration ändert. Zudem kann man die IP auch jederzeit manuell ändern.

Erstelle lieber einen Token im localStorage, den du dann abgleichen kannst.

3. wenn Daten via Post kommen werden diese zuerst durch eine Funktion gejagt, die Schadcode entfernt, dann gelangen sie erst in die Login Funktion, welche dann die Daten mit den in der Datenbank hingelegten prüft.

Meinst du z. B. XSS? Du musst lediglich die Werte escapen, das kannst du mittels pdo->prepare() und ...->execute() realisieren, dafür brauchst du keine zusätzliche Funktion.

3

1. Das ist mir leider auch aufgefallen, da es sich ja um die Adresse des Gateways also dem Router handelt. Dann sind natürlich auch gleich alle anderen Geräte auch gesperrt.
Wie würde man deine Lösung unsetzen?

3. Das mache ich aus Prinzip, auch bei allen GET Parametern, oder generell alle Eingaben die vom Nutzer kommen.

0
35
Meinst du z. B. XSS? Du musst lediglich die Werte escapen, das kannst du mittels pdo->prepare() und ...->execute() realisieren, dafür brauchst du keine zusätzliche Funktion.

Prepared Statements sind ein Schutz gegen SQL-Injections und nicht gegen XSS. Für XSS eignen sich z.B. htmlentities.

0
10
@tavkomann

Stimmt, da hab ich was verwechselt. Danke für den Hinweis!

0

3. wenn Daten via Post kommen werden diese zuerst durch eine Funktion gejagt, die Schadcode entfernt, dann gelangen sie erst in die Login Funktion, welche dann die Daten mit den in der Datenbank hingelegten prüft.

Verstehe ich nicht. Sofern du die PHP-Methode password_verify nutzt, kann bzgl. XSS nicht viel passieren. Aber gut, safety first, lieber so.

Ich habe bedenken, was die Speicherung von IP-Adressen angeht. Warum blockierst du den Nutzer nicht durch einen Eintrag in deiner Datenbank? So kommst du um die Speicherung der IP herum.

3

Was meinst du mit den „Nutzer“. Vor dem erfolgreichen Login, weiß ich ja noch nicht wer der Nutzer ist. Da bleibt als erkennen doch nur die IP oder?

0
3

Das Problem ist, dass momentan nicht nur das eine Gerät blockiert wird, sondern alle Geräte, die über das Gateway (also den Router) reingehen.

1
36

Du musst auf jeden Fall die IP-Adressen NICHT standardmäßig speichern. Um bestimmte Nutzer zu blockieren, füge ein Feld in der Nutzerdatenbank ein. Wenn sich ein blockierter Nutzer einloggt, zeige eine Fehlermeldung direkt nach dem Login an.

Wenn du auch unangemeldete Website-Besucher blockieren willst, erstelle eine Tabelle mit blockierten IP-Adressen. Dann musst du bei jedem Website-Aufruf die IP-Adresse mit der Tabelle abgleichen.

1
3

Für gesperrte Nutzer die sich anmelden habe ich hochprofessionell :D ein Parameter in der Benutzertabelle.

Aber die nicht angemeldeten Nutzer die sollen halt nicht 100 mal ein falsches Passwort eingeben deswegen werden sie halt nach den 10 versuchen für 24 Stunden gesperrt.

0
35
Sofern du die PHP-Methode password_verify nutzt, kann bzgl. XSS nicht viel passieren.

Es gibt noch weitaus mehr Wege für XSS als nur das Passwort.

0

Sky Go Login gesperrt

Hi habe folgendes Problem und zwar wollte ich mich bei der sky go App anmeldet schön und gut nun wenn ich meine kundennummer und pin eingegeben habe steht dort das mein Login gesperrt wurde also ging ich auf sky.de um mein Login wieder freizuschalten 15 min gewartet immer noch gesperrt halbe Stunde gewartet immer noch gesperrt dann hab ich bei sky angerufen die schließlich das gleiche gemacht haben nach 15 immernoch gesperrt. Heute wieder angerufen das gleiche Spiel. Weiß nicht mehr weiter kann mir da jmd helfen.

...zur Frage

Wie kann ich mein C# Form Programm mit einer Datenbank oder einem Jimdo Webspace verbinden?

Hallo. Ich habe bis jetzt die Logins in meinem Login System innerhalb der Anwendung gespeichert. Dies ist aber sehr unsicher und belastend wenn du zB. ein Login eintragen willst musst du eine neue Version raus bringen. Ich Möchte nun Login Daten ändern / hinzufügen können über eine Datenbank auf meinem Server oder einem Jimdo Webspace.

Bitte um Hilfe..

LG

Danke im Vorraus!

...zur Frage

Php Daten in Datenbank einfügen?

Ich bin schon relativ weit, aber aus irgendeinem Grund kann ich keine Strings in die Datenbank reinbekommen (Die einzelnen Spalten sind als VarChar definiert). Zahlen werden aber problemlos genommen und eingetragen.

Könnte mir jemand helfen ?

...zur Frage

Warum muss ich eigentlich bei NETFLIX fast jedesmal meine Login-Daten mühevoll eingeben?

Bei meinem LG-Fernseher ist es sehr mühevoll, die Login-Daten einzugeben, weil ich nur so einen 08-15 Fernbedienung habe, wo jeder Buchstabe eine (gefühlte) halbe Stunde dauert, bis man ihn eingegeben hat.

Vor allem bei NETFLIX ist das extremst nervig. Gibt es keine Möglichkeit, die Login-Daten dauerhaft zu speichern?!

...zur Frage

MySQL Datenbank Tabelle über php ausgeben

Guten Tag lieber Community,

ich würde gerne online auf meiner Website eine Geräteliste erstellen. In dieser sollten die Geräte Namen und eine kurze beschreibung stehen. Da ich allerdings keinen Bock habe immer die Daten auf die Website einzutragen, würde ich die Daten gerne in eine MySQL Datenbank legen. Nun ist meine Frage, ist es möglich die Daten aus der MySQL Datenbank direkt in die HTML Tabelle zu bekommen, und wenn ja, wie?

...zur Frage

PHP und CSS in HTML Datei?

Hallo Leute Ich will Daten aus ner Datenbank in einer html Datei ausgeben Wie macht man das normal da Apache ja keine PHP Anweisungen in ner HTML Datei verarbeitet Die HTML Datei ist auserdem noch mit CSS gestaltet daher kann ich das ganze nucht als php Datei machen

Ich frag mich wie man das normalerweise macht es wird ja oft etwas aus ner Datenbank ausgegeben in HTML seiten

Danke schon mal

...zur Frage

Was möchtest Du wissen?