PHP Bewerten der Sicherheit eines Login-Systems

  • Ersteller Ersteller SebastianBW
  • Erstellt am Erstellt am
Sieht erst mal nicht nach der schlimmsten Variante aus. Prepared Statements sind schon mal ne gute Sache, lediglich der eigentliche Schutz des Geschützten Bereichs, der sich nur auf die Prüfung der Existenz (nicht des validen Inhalts!) einer Session-Variable bezieht, scheint mir auf den ersten Blick dürftig.

Wer ein mal einen gültigen Login hatte, kann in den Dev-Tools sehen welche Werte in der Session dafür hinterlegt wurden. Diese kann man auch vortäuschen, ohne über das Login-Formular zu gehen und sich direkt am geschützten Bereich einloggen. Und im Fall dieses Skripts wird nicht mal der Inhalt geprüft, sondern nur "ob es überhaupt vorhanden ist" (sofern mich mein in die Jahre gekommenes PHP nicht trügt). Das wäre dann in etwa so, als wenn deine Haustür automatisch jedem aufmacht, der einen Schlüssel hat. Egal was für einen.

Halte es für angebracht, an der Stelle

PHP:
if(!isset($_SESSION['userid'])) {
    die('Bitte zuerst <a href="login.php">einloggen</a>');
}

wenigstens noch zu überprüfen, ob der Inhalt der Session-Variable "userid" auch dem eines gültigen/nicht-gelöschten/etc. Users entspricht.
 
Hi Andrew und danke für den Support.

Soll ich dann vor der if-Abfrage eine Datenbankabfrage machen, welche User es in der Datenbank gibt, die user IDs in einer Liste speichern und dann prüfen, ob die $_SESSION['userid'] in der Liste vorkommt?
 
Zum Beispiel. Abhängig davon, was du noch genau mit deinen Usern so anstellen können magst (z.B "deaktivierte" Nutzer, Nutzer die als gelöscht markiert wurden aber es noch nicht sind, Nutzer die eine mehrstufige Registrierung erst komplett durchlaufen haben müssen bevor sie berechtigt sind etc.) würde ich einfach eine Funktion schreiben, die wirklich nur die User auflistet, die Zugriff haben sollten (alle anderen nicht) und dann eben überprüft, ob in den übrig gebliebenen die übergebene ID auftaucht. Das ganze als Return mit TRUE/FALSE und du kannst den Bedingung oben recht einfach um eine weitere Abfrage erweitern und fertig.
 
Naja theoretisch gibt es nur 2 Benutzer und sonst soll/darf sich auch niemand registrieren. Ich könnte eigentlich auch die beiden User anlegen und danach den Registerteil ausblenden/auskommentieren.
 
Wann lernen es diese Tutorialschreiber endlich mal, dass man eine PDO-Instanz nicht ohne try-catch-Block erzeugen sollte?

http://php.net/manual/en/pdo.connections.php schrieb:
Warning
If your application does not catch the exception thrown from the PDO constructor, the default action taken by the zend engine is to terminate the script and display a back trace. This back trace will likely reveal the full database connection details, including the username and password. It is your responsibility to catch this exception, either explicitly (via a catch statement) or implicitly via set_exception_handler().
 
  • Gefällt mir
Reaktionen: HigH_HawK
Wann lernen diese Tutorialschreiber endlich mal PSR-2!
 
  • Gefällt mir
Reaktionen: r15ch13, HigH_HawK und Nase
  • Gefällt mir
Reaktionen: r15ch13
Das verlinkte Tutorial ist voller Angriffsvektoren und besteht aus schlecht lesbaren und wartbarem Code.

Folgende Dinge fallen mir auf:
* Spezifische anstatt generische Fehlermeldungen lassen für Angreifer Rückschlüsse auf Benutzernamen / E-Mails in der Datenbank zu (echo 'Diese E-Mail-Adresse ist bereits vergeben<br>'; )
* Keine Schutzmaßnahmen gegen Brute-Force Angriffe / "Bots" (captcha & failed login attemp counter mit Sperre des betreffenden Benutzers)
* Keine Behandlung von Ausnahmen (try ... catch), dadurch können ggf. interne Informationen leaken.
* Kein besonderer Schutz der PHP-Session vor dem Angriffsvektor "Session Fixitation"
* Benutzer können nicht gesperrt, nur aus der Datenbank gelöscht werden - gelöschte Benutzer mit einer laufenden Session werden jedoch nicht abgemeldet. - Das ständige Prüfen auf Sperren bei jedem Aufruf kostet aber auch Performance. Für Systeme mit dem Schutzstatus "hoch" ist das sinnvoll, darunter nicht unbedingt.

Was gut gemacht wurde:
* PDO prepared Statements und SQL Servervariablen
* Das Verwenden von password_hash und password_verify

Was schlecht gemacht wurde:
* die o.g. Angriffsvektoren
* Kein relevantes Code-Styling (PSR-2)
* überflüssige SPAM-Kommentare ($showFormular = true; //Variable ob das Registrierungsformular anezeigt werden soll)
* Keine Trennung Logik von Ausgabe usw. (MVC oder ähnliche Architekturmodelle), keine Abstraktion, kein Schichtmodell
* Ausführungsabbrüche anstatt sinnvolle Ausnahmebehandlung (das Verwenden von die("Fehlerstring"); )
* Kein Input-Filter - da wird auch wieder mit $_POST gearbeitet...

Was nicht stimmt, was hier im Thread jedoch erzählt wurde:
$_SESSION['userid'] wird von den verlinkten Skript immer eine gültige BenutzerID enthalten.
$_SESSION['userid'] kann nicht von außen von einen Client gesetzt / manipuliert / gelesen / gelöscht werden.
$_SESSION['userid'] bleibt nur, je nach Konfiguration, im Standardfall sind es circa 24 Minuten seit dem letzten Refresh der Session, gültig. Danach läuft die Session ab, sofern sie nicht erneuert oder beendet wurde. Abgelaufene Sessions werden im Standardfall bei 1/1000 Aufrufen eines PHP-Server-Threads vom GC aufgeräumt und dann auch vom Server gelöscht.

Die Prüfung auf isset($_SESSION['userid']) reicht also vollkommen aus, um zumindest diesen Teil des Schutzes zu gewährleisten. Ich verweise aber auch auf den Angriffsvektor "Benutzer können nicht gesperrt, nur aus der Datenbank gelöscht werden"
 
Zuletzt bearbeitet: (Typos === (Wärme + Gehirn))
SebastianBW schrieb:
Punktabzug gibts schon allein wegen der Verwendung von PHP. Nicht das man nicht auch mit PHP ne sichere Anwendung hinkriegt, aber PHP macht es halt einem schwerer und legt einem unnötig Fallstricke in den Weg.

Das Du hier ein Bastelskript nehm willst, gibt dem ganzen dann aber wirklich den Rest.

Das ist ein Tutorial. Das ist nicht dafür da, die ne prduktionsreife Lösung in die Hand zu geben, sondern anhand dessen zu lernen, wie man sowas implementieren kann.
Bestenfalls (und nicht mal das sehe ich hier) kann man das als Grundlage nehmen, um daraus was brauchbares zu basteln.

Ansonsten gilt eigentlich, wie so oft: Wenns eine etablierte fertige Lösung gibt (Framework, whatever), nimm die und versuch nicht besser zu sein als Leute, die sich mit der Thematik auskennen.

Das wars eigentlich schon. Was hier sonst noch genannt wurde ist natürlich nicht falsch und als Erläuterung auch durchaus interessant, aber sind eigentlich lediglich "Folgefehler".
 
Das die Leute nicht ordentlich programmieren können liegt aber nicht an PHP ;)
PHP hat eher das "Problem", dass es zugänglicher und fehlertolleranter ist als viele andere Sprachen.
Das macht es für Anfänger recht einfach damit Ergebnisse zu erzielen.

Wenn es um Security geht finde ich jedoch mindestens genau so viel kaputten Code in C oder Go oder Python, wenn ich anfange zu suchen. Bei Python stimmt zumindest immer das Code-Styling, da das dort eine Relevanz für den Interpreter hat.
Security hat wenig mit der eigentlichen Programmierung sondern oftmals mit der Systemarchitektur und dem Softwaredesign zu tun.
 
Guten Abend

Die Wendung was das Tutorial angeht hab ich nicht erwartet. Ehrlich gesagt ist es in keinster Weise mein bestreben, etwas besser zu machen als bestehende Frameworks. Ich kann C#, aber keineswegs bin ich aufm aktuellen Stand der Technik was PHP etc. angeht. Ich hab ein paar Websites mit Bootstrap 3 und 4 für Freunde gemacht - das wars.

Ich bin ja auch auf der Suche nach etwas fertigen, aber konnte und kann nicht einschätzen, wenn ich was gefunden habe, ob das was taugt.

NPC schrieb:

Das erste und letzte Framework scheint mir am aktuellsten (wegen der letzten Änderungen).

Ich würde PHPAuth tendieren. Ist das dann empfehlenswert, aktuell, sicher und passend für mich (Bootstrap 3 und 4 Webseite)?

Besten Dank
Basti
 
Bootstrap ist ein Front-End-Framework, wir reden hier vom Backend. Eventuell wäre es auch empfehlenswerter, wenn du direkt auf ein komplettes PHP-Framework setzt, anstatt nur auf einzelne Komponenten.
 
ayngush schrieb:
Das die Leute nicht ordentlich programmieren können liegt aber nicht an PHP ;)
PHP hat eher das "Problem", dass es zugänglicher und fehlertolleranter ist als viele andere Sprachen.
Das macht es für Anfänger recht einfach damit Ergebnisse zu erzielen.
Kann man so sehen. Und widerspricht ja auch nicht meiner Grundaussage und ändert auch nix an der Folge.

ayngush schrieb:
Wenn es um Security geht finde ich jedoch mindestens genau so viel kaputten Code in C oder Go oder Python,
Kaputten Code findest Du immer. Aber darum ging es auch gar nicht. Es ging darum, wie einfach oder schwer es Dir eine Sprache macht tatsächlich "kaputten Code" zu bauen.
Insofern ist auch C ein relativ schlechtes Beispiel. Weil auch C hat relativ viele Fallstricke und es ist da schon fast ne Kunst ein fehlerfreies Programm hinzubekommen, insbesondere mit der ganzen Zeigerarithmetik.

ayngush schrieb:
Bei Python stimmt zumindest immer das Code-Styling, da das dort eine Relevanz für den Interpreter hat.
Was ich persönlich eher nervig finde, aber jetzt auch kein Punkt wo ich sage, dass der kriegsentscheidend ist. Eher ne belanglose Geschmacksfrage.

ayngush schrieb:
Security hat wenig mit der eigentlichen Programmierung sondern oftmals mit der Systemarchitektur und dem Softwaredesign zu tun.
Jaein. Wenn Du eine Programmiersprache verwendest, die prinzipbedingt keine BufferOverflows erlaubt, dann brauchst Du schon mal Dich darum nicht mehr kümmern.
Auch ein gutes Typsystem hilft enorm viele (sicherheitsrelevante) Fehler zu vermeiden.

Die Strenge einer Sprache hilft natürlich auch. Wenn beispielsweise der Haskell-Compiler was akzeptiert, dann ist der Code auch schon von vielen Fehlern automatisch befreit die Dir bei Python, PHP usw. erst zur Laufzeit auf die Füße fallen würden.
 
Das PHPAuth ist vertrauenswürdiger aus. Zwar auch nicht ganz an PSR-2 gehalten. Dafür gibt es Tests, Namespaces und es wird CamelCase benutzt :D
 
Nun hab ich doch nochmal eine Frage. Ich habe mich für das andere PHP login system entschieden https://github.com/therecluse26/PHP-Login, da die Dokumentation von PHPauth nicht sonderlich umfangreich ist.

Dort muss man zu Beginn bei der Autoinstallation Datenbankinformationen angeben. Mein Webspace ist bei allinkl und ich habe die Datenbank angelegt z.B.

Datenbankname: d03abc85
Nutzername: d03abc85
Passwort: xxx123xxx

Die Autoinstallation möchte aber folgende Daten:
auto_install_form.png


Bei DB User, DB Name und DB Password habe ich die obigen angegeben.

Aber was soll ich bei den anderen eintragen? Habe folgendes eingetragen und wenn die Installation dann beginnt, kommt beim Fortschrittsbalken "null" und es klappt nicht:

Database Hostname: localhost
Root Install Path: \
Base URL: https://www.meinewebseite.de:443


Hier noch die Fehlermeldung:
Warning: chmod(): No such file or directory in /www/htdocs/w01569af/install/installscript.php on line 354


UPDATE:
Die Installation hat nun geklappt, aber die CSS Files werden nicht geladen. In der Develop Console vom Chrome kommen diese Meldungen:
Mixed Content: The page at 'https://www.mywebsite.de/' was loaded over HTTPS, but requested an insecure stylesheet 'http://www.mywebsite.de/login/css/main.css'. This request has been blocked; the content must be served over HTTPS.

Muss die Installation nochmal durchführen. Ich befürchte, dass das PHP Login System nicht für HTTPs ausgelegt ist
 
Zuletzt bearbeitet von einem Moderator:
Die main.css wird mit der base_uri eingebunden. Prüfe also nochmal, ob du bei der Installation die Base URI auch wirklich mit https angegeben hast. Dazu kannst du auch direkt in der Datenbank-Tabelle app_config nachschauen.
 
Ja, das hat nun auch gepasst, aber die Installation ging trotzdem nicht richtig.

Die Adminseite wird zwar dargestellt, aber CSS und JS fehlen. Also in der Console kommen einige Fehler, dass Bootstrap, jquery, usw. nicht vorhanden sind. Hab dann von Hand alle aus dem Installationsordner an den entsprechenden Pfad gemacht und nun gehts.

Nur leider weiß ich natürlich nicht, welche Funktionalität durch die fehlerhafte Installation beeinflusst wurde.

Da treten haufenweise Fehler auf, auch in Bezug auf https und dann noch das "alte" Bootstrap 3. Ich werde mal abwarten. Vielleicht gibts für das Framework bald ein Update oder vielleicht finde ich noch ein anderes, aber da war ich bisher mit der Suche erfolglos. Danke bis hierin für den Support.
Ergänzung ()

Denke das PHPAuth wäre das sinnvollste, aber da reicht mein können nicht aus und ein Tutorial oder Beispiel bieten die Autoren nicht an
 
Zuletzt bearbeitet von einem Moderator:
Zurück
Oben