PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Sicherheit bei Webanwendung/Login-System


Ben Carter
2022-04-22, 09:13:56
Hallo!

Üblicherweise überlasse ich dem Framework, das ich nutze, die ganzen Sicherheitsrelevanten Dinge, doch in diesem Fall muss ich mich selbst um eine User-Verwaltung und ein Login-System kümmern. Ich habe mich ein wenig damit beschäftigt, will aber nochmals sichergehen, ob ich nichts vergessen habe. Vielleicht hat jemand von euch mehr Erfahrungen damit. Verwendet wird PHP (8/8.1), JavaScript und MySQL. Login erfolgt mittels E-Mail Adresse und Passwort.

Verbindung nur mit SSL (https) möglich.
Passwort muss eine Mindestlänge von 10 haben, Groß-/Kleinbuchstaben, Zahlen und zumindest ein Sonderzeichen beinhalten.
Beim Erstellen des Users erzeuge ich einen Salt, indem ich eine UUID v4 erzeuge und diese mit bcrypt hashe. User bekommen eine GUID (ebenfalls UUID v4) und nicht nur eine einfache User-ID
Passwort wird mit Salt erweitert (Teile des Salts davor, ganzer Salt danach) und mit bcrypt gehasht.
Da es eine dynamische Webanwendung ist, erzeuge ich beim Login zusätzlich noch ein Token, dass ich an den JavaScript-Teil übergeben, der zusätzlich zu der User-GUID übergeben werden muss und dieses Token muss in weiterer Folge immer zusätzlich zur User-GUID mitgegeben werden, um zu verhindern, dass die Session gekapert wird. Das gleiche mache ich auch mit der IP-Adresse. Auch diese wird in der Session vorgehalten und bei jedem Aufruf geprüft.
2FA mit E-Mail optional -> darf ich leider nicht verpflichtend machen

Allgemeine Sicherheitsvorkehrungen:
Datenbank ist nur vom Webserver aus erreichbar und von nirgendwo anders
Pro Installation wird ein eigener API-Key verwendet, der im HTTP-Header mitgegeben werden muss
Um die allgemeine Konfiguration der Server brauche ich mich nicht zu kümmern, das macht jemand, der auch Ahnung davon hat

Ich wäre dankbar, wenn ihr mir mitteilt, ob ich ggf. noch was übersehen habe.

lg Ben

lumines
2022-04-22, 10:30:02
Üblicherweise überlasse ich dem Framework, das ich nutze, die ganzen Sicherheitsrelevanten Dinge, doch in diesem Fall muss ich mich selbst um eine User-Verwaltung und ein Login-System kümmern.

Hat das irgendeinen Grund? Es gibt natürlich auch diverse Frameworks (gerade) für PHP.

Passwort muss eine Mindestlänge von 10 haben, Groß-/Kleinbuchstaben, Zahlen und zumindest ein Sonderzeichen beinhalten.

Warum so eine einschränkende Anforderung? Wer Diceware nutzt, wird sich darüber eventuell ärgern.

Wenn du schwache Passwörter blocken willst, würde ich eine Blacklist integrieren, die bekannte / geleakte Passwörter blockt. Viel mehr kannst du nicht machen. Es ist unmöglich über solche Policies sichere Passwörter zu erzwingen.

Beim Erstellen des Users erzeuge ich einen Salt, indem ich eine UUID v4 erzeuge und diese mit bcrypt hashe. User bekommen eine GUID (ebenfalls UUID v4) und nicht nur eine einfache User-ID

Hört sich für mich unnötig kompliziert und potentiell unsicher an. UUIDv4-IDs müssen nicht zwangsläufig aus einem kryptografisch sicheren Zufallsgenerator stammen. Das muss für einen Salt aber gewährleistet sein.

Für einen Salt beziehst du einfach die entsprechende Anzahl Bytes aus einem kryptografisch sicheren Zufallsgenerator. Wenn ich das richtig sehe, sollte das bei PHP so gehen: https://www.php.net/manual/en/function.random-bytes.php

Allerdings glaube ich nicht, dass das notwendig ist, denn:

Passwort wird mit Salt erweitert (Teile des Salts davor, ganzer Salt danach) und mit bcrypt gehasht.

Wenn ich mir die Doku zu password_hash() durchlese, sehe ich, dass man direkt einen Salt als Parameter für bcrypt mitgeben kann. Du versuchst hier eine Art Wrapper darum zu bauen und den Salt schon vorher zu integrieren, was vermutlich keine gute Idee ist.

Es ist allerdings sogar so, dass die Option einen Salt manuell mitzugeben deprecated ist und in deiner verwendeten PHP-Version ignoriert wird:

Warning: The salt option is deprecated. It is now preferred to simply use the salt that is generated by default. As of PHP 8.0.0, an explicitly given salt is ignored.

Quelle: https://www.php.net/manual/en/function.password-hash.php

Insofern: Entferne alles rund um deine selbstgenerierten Salts und lass alles password_hash() erledigen. Es erzeugt automatisch einen entsprechenden Salt.

Ben Carter
2022-04-22, 10:58:45
Hallo,
danke für deine Rückmeldung!

Hat das irgendeinen Grund? Es gibt natürlich auch diverse Frameworks (gerade) für PHP.
Es soll gewissermaßen einfach und erweiterbar bleiben mit Schnittstellen zu anderen Systemen, ggf. auf diverse Datenbanksystem portierbar sein, auch wenn vorerst auf MySQL entwickelt wird, kommt SQL-Server und Oracle fix noch dazu. Ich habe auf die Schnelle nichts gefunden, was den Anforderungen entspricht.

Warum so eine einschränkende Anforderung? Wer Diceware nutzt, wird sich darüber eventuell ärgern. Wenn du schwache Passwörter blocken willst, würde ich eine Blacklist integrieren, die bekannte / geleakte Passwörter blockt.
Grundsätzlich ist es per Regex konfigurierbar, aber die Anforderung an das Kennwort entspricht somit den Anforderung anderer eingesetzter Software und somit ist sichergestellt, dass die Passwortanforderungen überall den gleichen Mindestlevel haben. Es wird vermutlich dazu kommen, dass sich der User bei System A authentifiziert und System A wiederum den User an System B authentifiziert. Wäre jetzt die Passwortanforderung an System A geringer als an System B wäre die Anforderung bei B umgangen. Im Grunde ist es am Ende aber so oder so Unternehmensrichtlinie.


Hört sich für mich unnötig kompliziert und potentiell unsicher an. UUIDv4-IDs müssen nicht zwangsläufig aus einem kryptografisch sicheren Zufallsgenerator stammen.

Für einen Salt beziehst du einfach die entsprechende Anzahl Bytes aus einem kryptografisch sicheren Zufallsgenerator. Wenn ich das richtig sehe, sollte das bei PHP so gehen: https://www.php.net/manual/en/function.random-bytes.php
random_bytes wird für die UUID-Generierung verwendet.

Allerdings glaube ich nicht, dass das notwendig ist, denn:

Wenn ich mir die Doku zu password_hash() durchlese, sehe ich, dass man direkt einen Salt als Parameter für bcrypt mitgeben kann. Du versuchst hier eine Art Wrapper darum zu bauen und den Salt schon vorher zu integrieren, was vermutlich keine gute Idee ist.

Es ist allerdings sogar so, dass die Option einen Salt manuell mitzugeben deprecated ist und sogar in deiner verwendeten PHP-Version ignoriert wird:

Quelle: https://www.php.net/manual/en/function.password-hash.php

Insofern: Entferne alles rund um deine selbstgenerierten Salts und lass alles password_hash() erledigen. Es erzeugt automatisch einen entsprechenden Salt.
Das ist ein guter Hinweis. Ich habe das Salt bislang nicht an die Funktion übergeben, sondern selbst zuvor hinzugefügt. Aber ich kann natürlich auch gleich den Salt der Funktion benutzen.

lg Ben

][immy
2022-04-22, 11:12:44
Wenn möglich würde ich empfehlen generell Abstand von einem eigenen Passwort system zu nehmen und stattdessen Google/MS/... Accounts empfehlen. Das erspart dir auf deiner Seite die Passwortsicherheit und du würdest dich nur noch um die Benutzerrechte kümmern müssen.
Ein eigenes System bringt leider meist mehr Unsicherheiten rein.

Ben Carter
2022-04-22, 11:15:35
Da es im Unternehmensumfeld genutzt wird, ist das leider keine Option. Wahrscheinlich kommt auch noch ein SSO/NTLM dazu.

lumines
2022-04-22, 11:20:17
Es soll gewissermaßen einfach und erweiterbar bleiben mit Schnittstellen zu anderen Systemen, ggf. auf diverse Datenbanksystem portierbar sein, auch wenn vorerst auf MySQL entwickelt wird, kommt SQL-Server und Oracle fix noch dazu. Ich habe auf die Schnelle nichts gefunden, was den Anforderungen entspricht.

Na ja, gerade bei dieser Anforderung sollte man schon sehr stark über ein Framework nachdenken. Doctrine, welches z.B. von Symfony verwendet wird, unterstützt sowohl MySQL / MariaDB, Oracle, MS SQL-Server, PostgreSQL und SQLite. Viel einfacher wirst du deine Anwendung nicht auf mehrere Datenbanksysteme portabel halten können.

Wenn du aber mehrere und unterschiedliche Datenbanken (aus welchen Gründen auch immer) anfragen musst, würde ich auch einmal ganz stark anzweifeln, dass du mit einer einzigen, monolithischen Anwendung, die im Grunde als Schnittstelle zwischen den Datenbanken agiert, weit kommen wirst. Ich entwickle zwar keine Anwendungen, aber aus Erfahrung sind solche Lösungen immer die Legacy-Systeme, die dann praktisch unwartbar vor sich hin vegetieren und irgendwann eingestampft werden, weil sie niemand mehr sinnvoll pflegen kann.

Da es im Unternehmensumfeld genutzt wird, ist das leider keine Option. Wahrscheinlich kommt auch noch ein SSO/NTLM dazu.

Gerade im Unternehmensumfeld kann man praktisch davon ausgehen, dass irgendwo ein Active Directory läuft und man sich da einklinken kann. Für viele Unternehmen sind selbstgestrickte Authentifizierungen sogar eher ein No Go. Genau deshalb spricht man ja auch von der "SSO Tax", also dass Lizenzgebühren bewusst an SSO gekoppelt sind, weil Unternehmen so stark auf SSO angewiesen sind.

Ben Carter
2022-04-22, 11:34:17
In einem konkreten Fall (Spedition) ist es so, dass ca. 300 Mitarbeiter im AD sind und ca. 2000 Fahrer nicht. Alleine für dieses Unternehmen brauche ich schon ein eigenes Login-System.

Ziel der Anwendung ist es u.a. Daten aus verschiedensten System zusammenzufassen, verarbeiten und anzuzeigen bzw. Benutzereingaben wieder an verschiedene System zu verteilen.

Teilweise wird die Anwendung Stand-Alone betrieben, teilweise wird sie in das von uns verwendete Framework (JobRouter) eingebettet.

Alles in allem ist es dennoch nicht wirklich komplex, sodass ich mir mit einem generellen Framework am Ende vermutlich deutlich mehr Arbeit aufhalse als es klein und einfach zu halten. Da das User-/Login-System natürlich ein sicherheitsrelevanter Teil ist, frage ich eben explizit dafür hier nach, um es entsprechend von Anfang an richtig anzugehen.

lg Ben

Exxtreme
2022-04-22, 11:45:53
Alles in allem ist es dennoch nicht wirklich komplex, sodass ich mir mit einem generellen Framework am Ende vermutlich deutlich mehr Arbeit aufhalse als es klein und einfach zu halten.

Meiner Erfahrung nach ist meist das Gegenteil der Fall. Der Punkt ist, Software, die es in die Produktion schafft ist praktisch nie simpel. X-D Hier schlägt das Pareto-Prinzip gnadenlos zu. Zweitens, bei Software in der Produktion wird Performance meist ein kritischer Faktor. In div. Frameworks steckt dann mehr Manpower für Optimierungen drin als wenn man sich selber was strickt. Und drittens, sobald es im Security-Sachen geht lieber die Finger davon lassen und besser gut abgestandene Bibliotheken nutzen.

Ach ja, will man mehrere Datenbank-Systeme abdecken dann bieten sich ORMs an. Doctrine scheint ziemlich beliebt im PHP-Umfeld zu sein.

https://www.doctrine-project.org/

Nur ist es so, wenn man ORMs nutzt dann am besten sich paar best practices reinziehen. Denn ORMs haben so ihre Eigenheiten mit denen man eher nicht rechnet.

Ben Carter
2022-04-22, 12:05:07
Nur dann muss ich es entsprechend des Frameworks entwickeln und habe Schwierigkeiten es anschließend auch in das von uns verwendete Framework einzubinden.

Ich weiß, dass die Hinweise und Tipps gut gemeint sind, ich stelle meine Anfrage aber schon so spezifisch, da ich mir ja schon Gedanken dazu gemacht habe. Zum Beispiel bietet JobRouter-Framework schon die Unterstützung für verschiedene Datenbanken. Ich habe bereits für ein anderes Projekt eine Klasse erstellt, die das mehr oder weniger 1:1 nachbildet, sodass ich den restlichen Code ohne Anpassungen übernehmen kann.

Mir wäre es auch am liebsten, wenn ich es einfach ausschließlich innerhalb von JobRouter entwickeln könnte, da ich mich dann um solcherlei Dinge eben nicht kümmern muss. Ist aber nicht.

Zusammengefasst: aus diversen Gründen ist es für mich am sinnvollsten und am einfachsten, das User-Management selbst zu entwickeln. Dabei sollte es möglichst sicher gestaltet werden. Dafür habe ich (gedanklich) schon die im Einstiegspost genannten Vorkehrungen getroffen und hoffe hier auf entsprechend dazu genannte Hinweise/Tipps zu erhalten, wie z.B. mit dem Salt bei password_hash geschehen.

Ich arbeite, abgesehen von drei Jahren in der Photovoltaik-Branche seit Anfang 2007 in der Softwareentwicklung und davor bereits 5 Jahre hobbymäßig. Bin also nicht unbedingt ein blutiger Anfänger, was das Einschätzen von Aufwänden betrifft bzw. wo es in Zukunft mit der entsprechenden Software hingeht.

Ich hoffe, es kommt nicht zu harsch rüber. Ich bin dankbar für jeden Tipp/Hinweis und mir ist auch bewusst, dass dafür jeder, der hier Antwort, Zeit aufwendet. Ich finde es mittlerweile nur etwas müßig, wenn man trotz recht konkreter Fragestellung immer an allen Ecken und Enden erklären muss, warum man etwas so macht, wie man es macht. Damit meine ich aber nicht nur das Forum hier. Im Grunde unterhalten wir und jetzt hier über diverse Frameworks und Abstraktionen anstatt darüber, wie man eben ein eigenes User-Management möglichst sicher macht.

lg Ben

Monger
2022-04-22, 12:18:53
Authentifikation und Payment sind die beiden "ach komm, wie kompliziert kann das schon sein?" Web Themen. Daran sind schon ziemlich große Firmen gescheitert.
Ich hab leider keine Ahnung von PHP. Wenn möglich, würde ich intern immer versuchen LDAP zu nehmen. Oft hat man ja eh bereits ne Rechteverwaltung, die sich mit solchen Apps deckt.