# Login-System für Webseite



## taks (14. September 2018)

*Login-System für Webseite*

Tag zusammen

Ich bin aktuell auf der Suche nach einem Login-System für eine Webseite.
Die Webseite soll HTML, CSS und PHP nutzen.
Geplante User Anzahl dürfte etwa um die 50 sein.

Nach einigen Recherchen bin ich auf dieses Tutorial gestossen:
Creating a User Login System with PHP and MySQL - Tutorial Republic

Hört sich für mich recht vernünftig an, auch was Fehlerbehandlung und Codeeinschleusen etc. betrifft.

Aber ich wäre trotzdem noch um die Meinung von jemanden mit mehr Knowhow im Bereich PHP froh ^^
Oder habt ihr ein anderes Tutorial zur Hand?


Gruss taks


_Edit: 
Noch eine Frage zum Tutorial oben:
In der config.php werden ja die Zugangsdaten für die Datenbank gespeichert.
Wie kann ich verhindern, dass jemand auf die config.php zugreifft und die Zugansdaten ausliest?_


----------



## grasshopper_1975 (15. September 2018)

*AW: Login-System für Webseite*

Für HTML und CSS kann ich Dir die Seite ans Herz legen:
W3Schools Online Web Tutorials

Da gibt es auch was nettes für PHP:
PHP Reference

Bin grad im Studium (angewante Informatik) und hatte letztes Semester das Fach Internettechnologie, dachte mir, einfach mal dein Link angucken...
Sieht soweit garnicht schlecht aus, jetzt kommt es halt drauf an, auf was für nem System Du das ganze umsetzen willst, also Win-Server oder Unix-Server,
da es da auch noch tonnenweise Stolpersteine gibt...

Aber als gutes Tutorial kannst du das auf jeden Fall schonmal nehmen, da soweit alle sicherheitsrelevanten Sachen, die mir soweit bekannt sind, beachtet 
worden sind.


----------



## fotoman (15. September 2018)

*AW: Login-System für Webseite*



grasshopper_1975 schrieb:


> jetzt kommt es halt drauf an, auf was für nem System Du das ganze umsetzen willst, also Win-Server oder Unix-Server,


Wo ist denn der Unterschied, ob Apache/MySQL unter Windows, Linux, Android oder sonstwas laufen? Der verlinkte Code macht keine AD-Abfrage sondern prüft einfach nur den PW-Hash gegen den in der DB gespeicherten. Und auch mit dem IIS kann man MySQL nutzen.

Was _config.php (oder andere php-Scripte) betrifft:
wenn der Webserver so konfiguriert ist, dass er .php Dateien als PHP interpretiert, dann führt auch ein wget config.php zur "Ausführung" des PHP auf dem Server und zur Rückgabe des Ergebnisses an den Aufrufer (also an wget). Damit landet beim Abrufer eine leere Datei.
_


----------



## DataDino (16. September 2018)

*AW: Login-System für Webseite*



grasshopper_1975 schrieb:


> Jetzt kommt es halt drauf an, auf was für nem System Du das ganze umsetzen willst, also Win-Server oder Unix-Server,
> da es da auch noch tonnenweise Stolpersteine gibt...


Stolpersteine gibt es dabei eigentlich nur, wenn man bestimmte Module bzw. Funktionalitäten einsetzen möchte. Unter anderem Memcached oder Redis (wobei es bei Redis mittlerweile auch eine Windowsversion gibt, die von MS selbst gewartet und verteilt wird). Aber in der Regel sind PHP Projekte auf verschiedenste Server übertragbar. Egal ob Windows, Linux oder anderen Unixoiden. Apache, NGINX, Lighttpd, Mongoose, IIS ... Klappt eigentlich immer ohne Probleme.
*
Zum verlinkten Tutorial:* Es sind solide Basics. Aber leider für die heutige Zeit nicht wirklich mehr ausreichend. Wenn dein Projekt ausschließlich in einem kontrollierten Intranet verwendet wird, dann kann man es so lassen. Sobald es allerdings über das gesamte Internet erreichbar sein soll, dann ist diese rudimentäre Umsetzung etwas mager.

1. Alle Formulare, die sich ohne Zugriffsrechte ausfüllen und abschicken lassen, sollte man gegen Bots absichern (Basis wäre eine CSRF-Protection wie im folgenden beschrieben). Dazu musst du es erzwingen, das dein Formular (in diesem Fall die Registrierung) auch aufgerufen wurde und nicht einfach nur die Daten direkt per HTTP-Request an das Target-Script gesendet werden. Das bedeutet also, das jeder Benutzer, egal ob registriert und eingeloggt oder nicht, eine Session bekommt. Innerhalb der Sessiondaten kannst du definieren, ob es sich um eine logged-in Session handelt oder die Session noch ausgeloggt ist. Im Zuge dessen erzeugt man beim Aufruf des Formulares einen temporären Schlüssel, der als Hidden-Inputfeld ins Formular eigetragen sowie in die Session geschrieben wird. Dieser wird beim absenden des Formulares wieder an den Server gesendet und mit dem, der in die Session geschrieben wurde, verglichen. Stimmt dieser, wurde das Formular regulär aufgerufen und die Daten können verarbeitet werden. Ansonsten wirft man eine Fehlermeldung und per Header einen passenden Statuscode zurück. Desweiteren sollte man beim Aufruf auch einen Timestamp in die Session eintragen und vor dem auswerten prüfen, ob zwischen Aufruf und Verarbeitung eine gewisse Zeit verstrichen ist. Bei einem 3-Zeiler wie diesem Formular sollte die Differenz in der Regel mehr wie 5 Sekunden betragen. Makrobots füllen solche Formulare in wenigen Millisekunden aus.

2. Die Password-Hash Bilbliothek von PHP ist so designed, das sich deine Software was die Verschlüsselung angeht so gut wie von selbst auf dem neuesten Stand hält. Und genau deswegen ist diese vereinfachte Nutzungsweise etwas ungünstig. Denn so wie in dem Tutorial wird es dazu führen, das es unterschiedlich gehashte Schlüssel in der Datenbank gibt. Es gibt noch eine Rehash-Funktion, mit der man prüfen kann, ob ein Hash noch dem aktuellen Standard entspricht. Wenn dem nicht so ist, sollte man das eingegebene Passwort beim Login direkt neu verschlüsseln und speichern, damit auch so viele wie möglich mit dem aktuellsten Standard-Algorithmus gehasht werden. Wenn man diese nicht einsetzen will, dann sollte man die Parameter der Hash-Funktionen manuell setzen.

3. Es fehlt noch ein Flood-Schutz. Hashing sowie Stringfunktionen erzeugen mehr Rechenlast als überwiegend Zahlenbasierte einfache Funktionen. Gerade die Hash-Bibliothek zielt auf einen erhöhten Kostenfaktor bei der Rechenleistung ab. Man sollte also bei zu vielen Zugriffen auf solche Scripts in kurzer Zeit die Zugriffe ohne intensiverer Verarbeitung abbrechen. Wenn man zum Ziel von DoS-Attacken wird, ist die einfachste Möglichkeit, den Server zu überfordern, ihn zum ständigen Hashen/Verschlüsseln zu zwingen. Das Loginscript ist die Ideale Basis für solche Angriffe. Man benötigt nur einen gültigen Nutzernamen und schon kann man mit genügend Requests den Server in die Knie zwingen. Die CSRF-Protection ist ein Anfang. Allerdings lässt sich das Loginscript nur schwer auf Zeit prüfen, da sich bei gespeicherten Zugangsdaten im Browser die Zeit zum ausfüllen des Formulares erheblich beschleunigen lassen und damit valide Benutzer beeinträchtigt werden könnten, wenn man einen zu großen Offset wählt. Deswegen sollte man hier noch zusätzlich einen Flood-Schutz einsetzen, um bei Makro-Bots die versuchen, DoS auf das Formular zu feuern, ab dem X-ten Aufruf in sehr kurzer Zeit einfach ein Bad-Request zurückwerfen.

Noch dazu gibt es einen Schönheitsfehler in dem Tutorial: Anstatt Trim bei jeder Nutzung der Daten zu verwenden, sollte man Trim für jedes Datenstück nur einmal nutzen, das Ergebnis in eine Variable schreiben und dann mit diesen weiterarbeiten. Das reduziert Rechenlast. Stringfunktionen sind in der Regel immer etwas rechenintensiver.

Ich habe gerade leider keine Links oder Tutorials für das ganze parat. Aber wie gesagt, deckt das verlinkte Tutorial nur die absoluten Basics ab und sollte meiner Meinung nach nicht mehr 1 zu 1 für eine Internetseite verwendet werden.


----------



## Gorblorex (17. September 2018)

*AW: Login-System für Webseite*

Doofe Frage: warum verwendest Du nicht gleich ein CMS? Wenn es Dir "nur" ums Lernen geht, dann ist das so OK, ich würde mir aber heutzutage nicht die Arbeit machen und das Rad zum x-mal neu erfinden. Schliesslich wurden schon fast alle gängigen Anforderungen von irgendjemanden mehr oder weniger professionell gelöst. Alternativen gibt es genügend (Processwire, Drupal, Joomla, ... - um nur einige zu nennen).


----------



## taks (17. September 2018)

*AW: Login-System für Webseite*

Danke für die Antworten 
Die Beiträge sehen schonmal sehr vielversprechend aus. Werde es mir heute Abend mal in Ruhe durchlsesen.

Noch ein paar Anmerkungen:
- Warum kein CMS: Der Zweck der Webseite ist eher mit einem ERP System zu vergleichen. Content wird ziemlich statisch sein, die Benutzer verwalten nur ihre eigenen Angaben und Stati (Verfügbare Arbeitskapazitäten). Bei Bedarf kann ich es gerne näher erläutern ^^ 
- Die Webseite soll bei meinem Hoster laufen, ich hab keinen eigenen Webserver zu betreuen. Der Hoster hält soweit alles auf dem aktuellsten Stand.
- Warum keine fertige Lösung: Zum einen brauch ich vermutlich nur 5% der gesamten Lösung welche potentiell auch mehr Sicherheitslücken hat. Zum anderen bin ich beim Hoster eingeschränkt mit dem Betreiben von ganzen Applikationen, da es sozusagen nur ein Webspace ist.


----------



## Gorblorex (17. September 2018)

*AW: Login-System für Webseite*

Hi,
also das mit dem Hoster / Webspace sollte kein Problem sein. Du richtest Dir eine my(maria)SQL Datenbank ein und lädst die PHP Seiten Deines CMS/ERP/etc. Systems hoch. Die meisten Systeme haben dann einen Installer, der dann alles soweit fertig einrichtet. Einen dedizierten root Server benötigt man hierfür nicht.
Ob das bei Dir Sinn macht oder nicht, musst Du selber entscheiden. Ja, die meisten Systeme haben ein Feature Overkill und man muss auch hinterher sein dieses aktuell zu halten. Aber: auf diese Systeme schauen zig Personen darauf und Sicherheitslücken werden in der Regel zeitnah geschlossen. Bei Deinem selbstprogrammiertem System weißt du ja nicht mal, ob Du nicht aus versehen eine Lücke eingebaut hast, die Hacker werden es Dir nicht verraten 
Früher habe ich auch alles lieber selbst programmiert, nach dem Motto: dann habe ich den Code im Griff. Mittlerweile bin ich davon abgerückt und benutze wo es geht bereits etablierte und gepflegte OpenSource Systeme. Security through obscurity ist einfach kein gescheites Sicherheitskonzept.
Aber wie bereits gesagt, die Entscheidung liegt bei Dir.


----------



## taks (17. September 2018)

*AW: Login-System für Webseite*

Soooo... ich hab mich mal durch alles durch gelesen/gearbeitet 



grasshopper_1975 schrieb:


> Da gibt es auch was nettes für PHP:
> PHP Reference


Gibt es einen Grund wieso sie da die Hash-Funktionen nicht aufführen?



fotoman schrieb:


> Was config.php (oder andere php-Scripte) betrifft:
> wenn der Webserver so konfiguriert ist, dass er .php Dateien als PHP interpretiert, dann führt auch ein wget config.php zur "Ausführung" des PHP auf dem Server und zur Rückgabe des Ergebnisses an den Aufrufer (also an wget). Damit landet beim Abrufer eine leere Datei.


Ok, gut zu wissen, dann schau ich mir mal die Server-Config an.



DataDino schrieb:


> *Zum verlinkten Tutorial:* Es sind solide Basics. Aber leider für die heutige Zeit nicht wirklich mehr ausreichend. Wenn dein Projekt ausschließlich in einem kontrollierten Intranet verwendet wird, dann kann man es so lassen. Sobald es allerdings über das gesamte Internet erreichbar sein soll, dann ist diese rudimentäre Umsetzung etwas mager.


Das Ganze hängt direkt im Internet, somit muss ich die Basics vom Tutorial ein bisschen aufpeppen 



DataDino schrieb:


> 1. Alle Formulare, die sich ohne Zugriffsrechte ausfüllen und abschicken lassen, sollte man gegen Bots absichern (Basis wäre eine CSRF-Protection wie im folgenden beschrieben). Dazu musst du es erzwingen, das dein Formular (in diesem Fall die Registrierung) auch aufgerufen wurde und nicht einfach nur die Daten direkt per HTTP-Request an das Target-Script gesendet werden. Das bedeutet also, das jeder Benutzer, egal ob registriert und eingeloggt oder nicht, eine Session bekommt. Innerhalb der Sessiondaten kannst du definieren, ob es sich um eine logged-in Session handelt oder die Session noch ausgeloggt ist. Im Zuge dessen erzeugt man beim Aufruf des Formulares einen temporären Schlüssel, der als Hidden-Inputfeld ins Formular eigetragen sowie in die Session geschrieben wird. Dieser wird beim absenden des Formulares wieder an den Server gesendet und mit dem, der in die Session geschrieben wurde, verglichen. Stimmt dieser, wurde das Formular regulär aufgerufen und die Daten können verarbeitet werden. Ansonsten wirft man eine Fehlermeldung und per Header einen passenden Statuscode zurück. Desweiteren sollte man beim Aufruf auch einen Timestamp in die Session eintragen und vor dem auswerten prüfen, ob zwischen Aufruf und Verarbeitung eine gewisse Zeit verstrichen ist. Bei einem 3-Zeiler wie diesem Formular sollte die Differenz in der Regel mehr wie 5 Sekunden betragen. Makrobots füllen solche Formulare in wenigen Millisekunden aus.


Ok, soweit alles klar. Hab mich bei CSRF ein bisschen eingelesen und das mit dem Session-Key wird auch in einigen Tutorials gut erklärt.
Muss mich wohl mal hinsetzen und ein Konzept erarbeiten, wie das Sicherheitsmanagement aufgestellt sein soll.
Grundsätzlich werde ich alles ausser dem Login Form nur mit eingelogter Session zulassen um mal die Angriffsfläche zu verringern.
Funktionen wie neue Benutzer erstellen oder Passwort zurücksetzen werde ich über einen Admin Benutzer mit entsprechenden Rechten lösen.



DataDino schrieb:


> 2. Die Password-Hash Bilbliothek von PHP ist so designed, das sich deine Software was die Verschlüsselung angeht so gut wie von selbst auf dem neuesten Stand hält. Und genau deswegen ist diese vereinfachte Nutzungsweise etwas ungünstig. Denn so wie in dem Tutorial wird es dazu führen, das es unterschiedlich gehashte Schlüssel in der Datenbank gibt. Es gibt noch eine Rehash-Funktion, mit der man prüfen kann, ob ein Hash noch dem aktuellen Standard entspricht. Wenn dem nicht so ist, sollte man das eingegebene Passwort beim Login direkt neu verschlüsseln und speichern, damit auch so viele wie möglich mit dem aktuellsten Standard-Algorithmus gehasht werden. Wenn man diese nicht einsetzen will, dann sollte man die Parameter der Hash-Funktionen manuell setzen.


Gut zu wissen. Wird wohl das einfachste sein, den Logarithmus selbst zu setzen und pro Benutzer die Art des verwendeten Logarithmus pro User zu speichern. 
So kann man beim Login einen Check fahren welcher bei einem Passwort mit altem Logarithmus einen rehash fährt.



DataDino schrieb:


> 3. Es fehlt noch ein Flood-Schutz. Hashing sowie Stringfunktionen erzeugen mehr Rechenlast als überwiegend Zahlenbasierte einfache Funktionen. Gerade die Hash-Bibliothek zielt auf einen erhöhten Kostenfaktor bei der Rechenleistung ab. Man sollte also bei zu vielen Zugriffen auf solche Scripts in kurzer Zeit die Zugriffe ohne intensiverer Verarbeitung abbrechen. Wenn man zum Ziel von DoS-Attacken wird, ist die einfachste Möglichkeit, den Server zu überfordern, ihn zum ständigen Hashen/Verschlüsseln zu zwingen. Das Loginscript ist die Ideale Basis für solche Angriffe. Man benötigt nur einen gültigen Nutzernamen und schon kann man mit genügend Requests den Server in die Knie zwingen. Die CSRF-Protection ist ein Anfang. Allerdings lässt sich das Loginscript nur schwer auf Zeit prüfen, da sich bei gespeicherten Zugangsdaten im Browser die Zeit zum ausfüllen des Formulares erheblich beschleunigen lassen und damit valide Benutzer beeinträchtigt werden könnten, wenn man einen zu großen Offset wählt. Deswegen sollte man hier noch zusätzlich einen Flood-Schutz einsetzen, um bei Makro-Bots die versuchen, DoS auf das Formular zu feuern, ab dem X-ten Aufruf in sehr kurzer Zeit einfach ein Bad-Request zurückwerfen .


Hatte sowieso vor ein Zugriffslogging zu erstellen. Da der DDoS ja nur wirklich Rechenaufwand bedeutet wenn der Angreifer einen korrekten Loginnamen hat, könnte man nach ~10 Loginversuchen in 30 Sekunden von einem Benutzer diesen "sperren" und die Anfragen direkt ohne hashen canceln.



DataDino schrieb:


> Noch dazu gibt es einen Schönheitsfehler in dem Tutorial: Anstatt Trim bei jeder Nutzung der Daten zu verwenden, sollte man Trim für jedes Datenstück nur einmal nutzen, das Ergebnis in eine Variable schreiben und dann mit diesen weiterarbeiten. Das reduziert Rechenlast. Stringfunktionen sind in der Regel immer etwas rechenintensiver.


 Ok, werd ich beachten.



Gorblorex schrieb:


> Hi,
> also das mit dem Hoster / Webspace sollte kein Problem sein. Du richtest Dir eine my(maria)SQL Datenbank ein und lädst die PHP Seiten Deines CMS/ERP/etc. Systems hoch. Die meisten Systeme haben dann einen Installer, der dann alles soweit fertig einrichtet. Einen dedizierten root Server benötigt man hierfür nicht.
> Ob das bei Dir Sinn macht oder nicht, musst Du selber entscheiden. Ja, die meisten Systeme haben ein Feature Overkill und man muss auch hinterher sein dieses aktuell zu halten. Aber: auf diese Systeme schauen zig Personen darauf und Sicherheitslücken werden in der Regel zeitnah geschlossen. Bei Deinem selbstprogrammiertem System weißt du ja nicht mal, ob Du nicht aus versehen eine Lücke eingebaut hast, die Hacker werden es Dir nicht verraten
> Früher habe ich auch alles lieber selbst programmiert, nach dem Motto: dann habe ich den Code im Griff. Mittlerweile bin ich davon abgerückt und benutze wo es geht bereits etablierte und gepflegte OpenSource Systeme. Security through obscurity ist einfach kein gescheites Sicherheitskonzept.
> Aber wie bereits gesagt, die Entscheidung liegt bei Dir.


Ich hab mich nochmals durch die Verfügbaren CMS und ERP System gewühlt, aber keines deckt ab was ich brauche, hat dafür massenhaft Zeug welches ich nicht brauche.
Ich gabe dir ja Recht, eine "fertige" Lösung wäre für mich auch interessant, aber gibt es anscheinend nicht ^^
Security through obscurity ist auch keineswegs was ich vorhabe. Darum Frage ich hier ja nach was es sonst noch so zu beachten gäbe.
Hab noch einige Artikel von CMS System Anbeitern durchgelesen, welche genauer auf mögliche Angriffsarten eingehen und ich hab da glaub erstmal alles Grundlegende gefunden. 
Ich werde dann wenn ich mal weiter bin einen Check durchführen welche Angriffsarten ich abgedeckt habe.


Vielleicht bin ich momentan noch ein bisschen naiv, aber ich glaube ich kriege das hin ^^

Danke nochmals für die Hilfe bisher. Ich melde mich wieder


----------



## RicoBrassers (18. September 2018)

*AW: Login-System für Webseite*



taks schrieb:


> Gut zu wissen. Wird wohl das einfachste sein, den Logarithmus selbst zu setzen und pro Benutzer die Art des verwendeten Logarithmus pro User zu speichern.
> So kann man beim Login einen Check fahren welcher bei einem Passwort mit altem Logarithmus einen rehash fährt.



Brauchst du nicht, das übernimmt PHP bereits für dich.
Wenn du die password_[...] Funktionen von PHP nutzt, werden die benutzen Optionen im gehashten Passwort eingearbeitet und können (im Gegensatz zum Passwort) auch wieder extrahiert werden.

Siehe: PHP: password_get_info - Manual

Ebenfalls interessant könnte für dich dabei auch die Funktion "password_needs_rehash" (PHP: password_needs_rehash - Manual) sein. Diese nimmt ein gehashtes Passwort und Einstellungen entgegen und sagt dir anschließend, ob das Passwort mit den gegebenen Optionen gehasht wurde.

Falls du die Möglichkeit hast, auf PHP >= 7.2.0 zu setzen,  dann würde ich dir das empfehlen. Dann kannst du bei password_hash nämlich statt Bcrypt Argon2I als Hashalgorithmus nutzen (Argon2I ist sicherer und effizienter als Bcrypt).
Netter Nebeneffekt: PHP setzt seit 7.2 auf eine neuere, aktuellere Krypto-Bibliothek, was also auch nochmal ein Gewinn an Sicherheit darstellt.

Übrigens: Das Wort, das du meintest, ist vermutlich *Algorithmus*, nicht Logarithmus.


----------



## BloodSteam (20. September 2018)

*AW: Login-System für Webseite*

Hier:
GitHub - G1K777/random


----------

