Ich möchte mir für ein Projekt eine Nutzerverwaltung neu aufbauen und beschäftige mich nun erst einmal damit, was man da alles beachten kann und/oder soll. Wird natürlich keine Hochsicherheitsanwendung, aber wenn man es schon anfängt, sollte es schon so gut sein, wie es mit gerechtfertigtem Aufwand implementierbar ist.
Grob sehe ich zwei Gefahren. Jemand ...
- loggt sich bei einem falschen Account ein
- übernimmt eine Session
Das wird jetzt eine etwas größere Liste, einfach damit mir keiner Ansätze erklären muss, die ich schon kenne, das wäre ja unnötige Arbeit
Der erste Fall ist für mich recht klar. Brute-Force-Angriffe durch begrenzte Login-Versuche verhindern und Passwort vernünftig gehasht mit Salt in der Datenbank speichern, da gibt es mit password_hash() inzwischen schon alles fertig.
Mich beschäftigt vorallem nun der zweite Punkt. Habe mir dafür "Session Management Basics - Session Security" auf php.net und noch die Beschreibung einiger Funktionen durchgelesen. Dabei habe ich mitgenommen, dass man vorallem session.use_strict_mode und session.use_only_cookies verwenden soll, um zu vermeiden, dass jemand seine Session-ID mit einem Link mitschickt und die Session-ID nicht nicht in den Metadaten irgendwo auftaucht. Außerdem kann dem Anwender keiner einen Link mit einer Session-ID darin schicken, die er dann verwende, womit der Angreifer dann die ID des Anwenders kennen würde. session.use_strict_mode schützen zudem davor, dass der Angreifer selbst die Session-ID bestimmen kann, also eine verwendet, die der Server selbst gar nicht kennt.
Weiter steht da, man sollte die Session nicht zu lange laufen lassen und nach einer gewissen Zeit durch eine neue Session ersetzen, wovon der Anwender natürlich nichts mitbekommt. In der Session sollte ein Ablaufdatum hinterlegt sein, damit die alte Session nicht ewig weiter verwendet werden kann.
Bei Erhöhung der Berechtigungen soll die Session-ID erneuert werden, damit ein Angreifer, der die alte Session-ID kennt, nicht plötzlich auch eine höhere Berechtigung hat.
Ferner wird im Kapitel "Session and Auto-login" empfohlen eine große Pseudozufallszahl als Cookie zu hinterlegen, die sich am besten mit jedem Seitenaufruf ändert und der Server immer mit der Datenbank abgleichen kann. Und generell sollte ich alle aktiven Sessions in der Datenbank mit Zusatzinformationen nachhalten.
Unter anderem Wikipedia empfiehlt noch die Session an eine IP oder einen Fingerprint des Clienten binden. Die Bindung an die IP bringt mit sich, dass der Anwender sich jeden Tag neu einloggen muss, nicht zielführend. Wäre höchstens sinnvoll IPs zu speichern, von denen aus zugegriffen wird und wenn die IP wechselt und die alte danach wieder auftaucht, dann wird es verdächtig.
__________________________________________
Das wäre glaube ich alles, was ich so an Methoden kenne bzw. gelesen habe. Einige Fragen stellen sich mir aber noch.
- Was bringt es einen Hash als weiteres Geheimnis in den Cookies zu speichern? Wenn ein Angreifer die Session-ID auslesen kann, dann doch auch das andere beliebig lange Geheimnis, egal ob er meine Cookies ausliest oder den Datenstrom mitliest. Macht für mich daher keinen großen Unterschied. Das bringt erst dann irgendetwas, wenn sich das geheimnis wirklich ständig ändert. Nur dann muss er lediglich einmal schneller den Server ansprechen als ich, schon wandert die Session zum Angreifer. Der Anwender merkt das nur, weil er plötzlich ausgeloggt ist. Ich könnte dann implementieren, dass mit einem falschen Geheimnis die Session gleich geschlossen wird. Nur dann befürchte ich, dass es ständig Probleme gibt, obwohl es keinen Angriff gab.
- Als "Fingerprint" fällt mir als erstes der User Agent ein, aber gleiches Problem wie oben, wer die Session-ID auslesen kann, bekommt ohne Mehraufwand auch meinen User Agent. Ich weiß, dass es da noch mehr als Fingerprint gibt, kenne mich da aber noch nicht so aus. Gibt es da noch etwas, was per PHP (also ohne JS) zu realisieren wäre, um den Clienten wiederzuerkennen?
- Und natürlich, habe ich was Wichtiges vergessen oder falsch verstanden?
Schon mal vielen Dank fürs Lesen!
Grob sehe ich zwei Gefahren. Jemand ...
- loggt sich bei einem falschen Account ein
- übernimmt eine Session
Das wird jetzt eine etwas größere Liste, einfach damit mir keiner Ansätze erklären muss, die ich schon kenne, das wäre ja unnötige Arbeit
Der erste Fall ist für mich recht klar. Brute-Force-Angriffe durch begrenzte Login-Versuche verhindern und Passwort vernünftig gehasht mit Salt in der Datenbank speichern, da gibt es mit password_hash() inzwischen schon alles fertig.
Mich beschäftigt vorallem nun der zweite Punkt. Habe mir dafür "Session Management Basics - Session Security" auf php.net und noch die Beschreibung einiger Funktionen durchgelesen. Dabei habe ich mitgenommen, dass man vorallem session.use_strict_mode und session.use_only_cookies verwenden soll, um zu vermeiden, dass jemand seine Session-ID mit einem Link mitschickt und die Session-ID nicht nicht in den Metadaten irgendwo auftaucht. Außerdem kann dem Anwender keiner einen Link mit einer Session-ID darin schicken, die er dann verwende, womit der Angreifer dann die ID des Anwenders kennen würde. session.use_strict_mode schützen zudem davor, dass der Angreifer selbst die Session-ID bestimmen kann, also eine verwendet, die der Server selbst gar nicht kennt.
Weiter steht da, man sollte die Session nicht zu lange laufen lassen und nach einer gewissen Zeit durch eine neue Session ersetzen, wovon der Anwender natürlich nichts mitbekommt. In der Session sollte ein Ablaufdatum hinterlegt sein, damit die alte Session nicht ewig weiter verwendet werden kann.
Bei Erhöhung der Berechtigungen soll die Session-ID erneuert werden, damit ein Angreifer, der die alte Session-ID kennt, nicht plötzlich auch eine höhere Berechtigung hat.
Ferner wird im Kapitel "Session and Auto-login" empfohlen eine große Pseudozufallszahl als Cookie zu hinterlegen, die sich am besten mit jedem Seitenaufruf ändert und der Server immer mit der Datenbank abgleichen kann. Und generell sollte ich alle aktiven Sessions in der Datenbank mit Zusatzinformationen nachhalten.
Unter anderem Wikipedia empfiehlt noch die Session an eine IP oder einen Fingerprint des Clienten binden. Die Bindung an die IP bringt mit sich, dass der Anwender sich jeden Tag neu einloggen muss, nicht zielführend. Wäre höchstens sinnvoll IPs zu speichern, von denen aus zugegriffen wird und wenn die IP wechselt und die alte danach wieder auftaucht, dann wird es verdächtig.
__________________________________________
Das wäre glaube ich alles, was ich so an Methoden kenne bzw. gelesen habe. Einige Fragen stellen sich mir aber noch.
- Was bringt es einen Hash als weiteres Geheimnis in den Cookies zu speichern? Wenn ein Angreifer die Session-ID auslesen kann, dann doch auch das andere beliebig lange Geheimnis, egal ob er meine Cookies ausliest oder den Datenstrom mitliest. Macht für mich daher keinen großen Unterschied. Das bringt erst dann irgendetwas, wenn sich das geheimnis wirklich ständig ändert. Nur dann muss er lediglich einmal schneller den Server ansprechen als ich, schon wandert die Session zum Angreifer. Der Anwender merkt das nur, weil er plötzlich ausgeloggt ist. Ich könnte dann implementieren, dass mit einem falschen Geheimnis die Session gleich geschlossen wird. Nur dann befürchte ich, dass es ständig Probleme gibt, obwohl es keinen Angriff gab.
- Als "Fingerprint" fällt mir als erstes der User Agent ein, aber gleiches Problem wie oben, wer die Session-ID auslesen kann, bekommt ohne Mehraufwand auch meinen User Agent. Ich weiß, dass es da noch mehr als Fingerprint gibt, kenne mich da aber noch nicht so aus. Gibt es da noch etwas, was per PHP (also ohne JS) zu realisieren wäre, um den Clienten wiederzuerkennen?
- Und natürlich, habe ich was Wichtiges vergessen oder falsch verstanden?
Schon mal vielen Dank fürs Lesen!
Kommentar