Sicherheitsfrage (Session und htaccess)

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von 3daycliff.

    Sicherheitsfrage (Session und htaccess)

    Guten Morgen,

    zurzeit arbeite ich an einem Login mit Registrierung.
    Das Ganze soll natürlich sicher sein, weshalb ich hier zwei Fragen habe.

    Ich hashe das Passwort mittels sha512, der Salt wird mittels dev urandom zufällig generiert (besteht also auch aus Sonderzeichen und Symbolen).
    AUch generiere ich einen Token, um CSRF zu verhindern.

    Bis dahin ist auch alles eigentlich sicher, nur weiß ich nicht, wie sicher das mit der Session ist.
    Ist alles richtig (sprich Passwort und Nutzername richtig), wird eine Session-Variable gesetzt und zwar als Wert der Username ($_SESSION['name'] = $username).
    Die geschützten Seiten überprüfen nun, ob die Session['name'] gesetzt wurde, falls ja, wird der INhalt angezeigt, andernfalls muss man sich erst einloggen.

    Nun meine Frage. Ist das sicher? Oder kann man die Session-Variable irgendwie manuell durch Manipulation oder so setzen, ohne das richtige PW einzugeben?

    Desweiteren möchte ich den Zugriff auf die Datenbank sichern - da ich leider keinen Ordner außerhalb des Webroot erstellen kann (habe meinen Webspace nur gemietet), versuche ich mittels .htaccess Dateien den Zugriff von außerhalb zu verbieten. Sprich in die Datei deny from all allow from IP reinschreiben. Habe das gemacht, also nur localhost erlaubt (127.0.0.1). Rufe ich das ganze auch manuell auf (webseite.de/secure/) steht da auch forbidden.
    Habe testweise mal das localhost entfernt, sollte also alles verbieten - manuell kann ich es auch weitehrin nicht aufrufen, dennoch kann das PHP-Skript darauf zugreifen. Sollte das nicht eigentlich auch nciht gehen?
    Sonst könnte ja jeder andere, der weiß, wo der DB-Zugriff definiert ist, darauf zugreifen? Nur ich (vom localhost) soll darauf Zugriff haben, sonst soll das nicht gehen.
    Geht sowas?

    Wäre toll, wenn ihr mir bei beiden Fragen behilflich sein könnt.

    Alles bezieht sich übrigens auf PHP.
    Warum ist das dann Off-Topic? Na gut.

    Ich hashe das Passwort mittels sha512
    Nutze lieber PBKDF2. SHA2 wird zwar häufig verwendet, es ist aber nicht für das Hashen von Passwörtern entwickelt worden. Die Schwachstelle hier ist die Geschwindigkeit.

    der Salt wird mittels dev urandom zufällig generiert
    Nicht gut (im Sinne von vollkommen paranoid). Besser ist, du nutzt die eingebauten PHP-Funktionen password_hash, password_verify und als Krönung noch password_needs_rehash. Da kann man nicht ganz so viel verkehrt machen.

    Nun meine Frage. Ist das sicher? Oder kann man die Session-Variable irgendwie manuell durch Manipulation oder so setzen, ohne das richtige PW einzugeben?
    Unter der Voraussetzung, dass keine anderen Schwachstellen existieren und PHP selbst keine entsprechende Lücken aufweist, kannst du davon ausgehen, dass die superglobale Variable ausschließlich von dir gesetzt wird.
    Auf der anderen Seite landet der Inhalt der Variablen beim Beenden des Scripts serialisiert in einer Datei. Bei einem schlecht konfigurierten Server besteht ggf. die Gefahr, dass die einzelnen Benutzer (du und die anderen Kunden des Hosters) nicht richtig gegeneinander abgeschottet sind und eventuell ein anderer Benutzer diese Dateien manipulieren kann.
    Jedes halbwegs professionelle System hat meist eine selbst programmierte Alternative und nutzt nicht die session_*-Funktionen. Teilweise wird auch einfach der Handler überschrieben (siehe session_set_save_handler-Funktion), um die Daten selbst zu verwalten, z.B. um sie in einer DB speichern zu können.

    Habe testweise mal das localhost entfernt, sollte also alles verbieten - manuell kann ich es auch weitehrin nicht aufrufen, dennoch kann das PHP-Skript darauf zugreifen. Sollte das nicht eigentlich auch nciht gehen?
    htaccess-Dateien sind eine Angelegenheit des Webservers (hier wohl Apache). Sobald dieser dein PHP-Script aufruft, hat er erst wieder was beim Übertragen der Daten zum Client/Browser zu sagen. In der Zwischenzeit kann dein PHP-Script machen was es will.
    Allgemein: Kann ein Angreifer irgendwie (PHP-)Code ausführen, hast du bei einem normalen Setup verloren.

    Sonst könnte ja jeder andere, der weiß, wo der DB-Zugriff definiert ist, darauf zugreifen?
    Wenn du deine Zugriffsdaten in einer PHP-Datei speicherst, sagen wir "secret.php", die z.B. so aussieht:

    PHP-Quellcode

    1. <?php
    2. $username = 'foo';
    3. $password = 'bar';

    sind sie relativ sicher, solange niemand Fremdes Code auf dem Server ausführen kann und der Server korrekt konfiguriert ist. Ruft jemand "example.com/secret.php" auf, bekommt er nur eine weiße Seite angezeigt. Das ist der Standardweg, solche Daten unter den oben genannten Umständen zu speichern.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „3daycliff“ ()

    3daycliff schrieb:

    Die Schwachstelle hier ist die Geschwindigkeit.

    Um dem entgegenzuwirken, lasse ich das ganze 1000 mal durchlaufen, bevor der eigentliche Hash generiert wird.

    3daycliff schrieb:

    Nicht gut (im Sinne von vollkommen paranoid). Besser ist, du nutzt die eingebauten PHP-Funktionen password_hash, password_verify und als Krönung noch password_needs_rehash. Da kann man nicht ganz so viel verkehrt machen.

    Danke, guck ich mir mal an. Habe allerdings gehört, dass dev u random eine sehr gute ZUfallsfunktion sein soll im Gegensatz zu bspw. rand().

    3daycliff schrieb:

    Unter der Voraussetzung, dass keine anderen Schwachstellen existieren und PHP selbst keine entsprechende Lücken aufweist, kannst du davon ausgehen, dass die superglobale Variable ausschließlich von dir gesetzt wird.

    Ok gut, danke.

    3daycliff schrieb:

    [...]sind sie relativ sicher, solange niemand Fremdes Code auf dem Server ausführen kann und der Server korrekt konfiguriert ist. Ruft jemand "example.com/secret.php" auf, bekommt er nur eine weiße Seite angezeigt.

    Ja, das ist logisch. Rurft das jemand so auf, erhält er keine Ausgabe. Nur könnte dann nicht einfach jeder eine PHP Datei schreiben und dort reinschreiben:

    PHP-Quellcode

    1. <?php
    2. include('http://fremdedomain.com/secret.php');
    3. $delete = "DELETE FROM bla blalaa.... ";
    4. ..
    5. ?>

    Das mal nur als Beispiel. Also könnte man die Datei nichtz einfach includen, wenn man weiß, wo diese liegt?
    Kann ich das includen von außerhalb verbieten?
    Die entfernte Datei mag vom entfernten Server (je nach Konfiguration) geparst werden oder nicht, aber sie muss weiterhin ein gültiges PHP-Skript ausgeben, weil die Ausgabe auf dem lokalen Server als PHP ausgeführt wird. Wenn die Ausgabe des vom entfernten Server nur ausgegeben werden soll, ist readfile() die bessere Wahl. Andernfalls muss sehr gut acht gegeben werden, dass das entfernte Skript sicher gültigen und erwünschten Code ausgibt!
    Quelle: php.net/manual/de/function.include.php

    Theoretisch kann man mit Include auch Skripte die auf einem anderen Server liegen, ausführen.
    Jedoch nur wenn der Server dies zulässt und die Datei als Quelldatei offen legt.
    Wenn dies im Server so eingestellt ist, kann man sich das Skript auch einfach im Browser angucken(?).
    Standardmäßig sollte das eig. jeder Server Verbieten, alleine dadurch das er selbst das Skript parst.
    Siehe dir mal include an.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Anluin“ ()

    Anluin schrieb:

    Die entfernte Datei mag vom entfernten Server (je nach Konfiguration) geparst werden oder nicht, aber sie muss weiterhin ein gültiges PHP-Skript ausgeben, weil die Ausgabe auf dem lokalen Server als PHP ausgeführt wird. Wenn die Ausgabe des vom entfernten Server nur ausgegeben werden soll, ist readfile() die bessere Wahl. Andernfalls muss sehr gut acht gegeben werden, dass das entfernte Skript sicher gültigen und erwünschten Code ausgibt!
    Quelle: php.net/manual/de/function.include.php

    Theoretisch kann man mit Include auch Skripte die auf einem anderen Server liegen, ausführen.
    Jedoch nur wenn der Server dies zulässt und die Datei als Quelldatei offen legt.
    Wenn dies im Server so eingestellt ist, kann man sich das Skript auch einfach im Browser angucken(?).
    Standardmäßig sollte das eig. jeder Server Verbieten, alleine dadurch das er selbst das Skript parst.
    Siehe dir mal include an.

    OK danke.
    Noch zwei Fragen - in der php.ini kann man noch zwei Einstellungen vornehmen - diese habe ich zurzeit aktiviert, habe aber gelesen, man sollte sie deaktivieren.
    Es handelt sich hierbei um allow_url_include und allow_url_fopen.
    Eure Meinung? Muss testen, ob meine Sachen auch ohne funktionieren. Habe gehört, das beeinträchtigt cUrl? Kann ich es dann nicht mehr nutzen? Parse u.a. eine Tabelle aus einer fremden Seite damit.
    Um dem entgegenzuwirken, lasse ich das ganze 1000 mal durchlaufen, bevor der eigentliche Hash generiert wird.
    Damit implementierst du teilweise das, was die password_*-Funktionen ohnehin schon tun. (Rad neu erfinden und so.) Die Iterationen sind sicher ein Schritt in die richtige Richtung, dennoch würde ich dir die PHP-Funktionen ausdrücklich empfehlen.

    Jein. /dev/urandom ist definitiv besser als die rand-Funktion von PHP (die im schlimmsten Fall auf die gleichnamige C-Funktion zurückgreift), allerdings hast du bei urandom keine Garantien über die Entropie. Die manpage rät hier auch, dass man ggf. /dev/random den Vorzug geben soll. In der Praxis ist das vermutlich aber kein Problem (wie gesagt: im Sinne von paranoid). password_hash verwendet im Idealfall einen CSPRNG (und im Worst-Case auch nur /dev/urandom). Verloren hättest du nichts, aber etwas gewonnen (neben Sicherheit): Kompatibilität für nicht Unix-Systeme (Windows).

    Ja, das ist logisch. Rurft das jemand so auf, erhält er keine Ausgabe. Nur könnte dann nicht einfach jeder eine PHP Datei schreiben und dort reinschreiben: [...] Das mal nur als Beispiel. Also könnte man die Datei nichtz einfach includen, wenn man weiß, wo diese liegt?
    Klar kann man sie includen. ABER: Die Datei wird vorher von deinem Webserver und PHP verarbeitet. D.h., dass jemand mit include 'http://example.com/secret.php'; nur die *Ausgabe* deines Scriptes erhält. Im oben genannten Bsp. also die leere Seite - einen Leerstring.

    Kann ich das includen von außerhalb verbieten?
    In dem Sinne nicht. Ist aber auch kein Problem.

    Es handelt sich hierbei um allow_url_include und allow_url_fopen.
    Die Einstellungen erlauben/verbieten dir Aufrufe wie z.B. include 'http://example.com'; oder fopen('http://example.com');.
    Per se ist keines der beiden ein Problem. Zu einer Sicherheitslücke kann es hier nur dann kommen, wenn der Benutzer die URL oder den Inhalt der abgerufenen Seite beeinflussen kann. Die erste Option kann man in aller Regel ohne schlechtes Gewissen abschalten.
    cURL sollte AFAIK von keiner der beiden Optionen beeinflusst werden.
    Vielen Dank für deine hilfreiche Antwort @3daycliff

    Werde mir deinen Ratschlag mit password_hash usw. zu Herzen nehmen und demnächst umsetzen.

    Dann ist es gut, dann bin ich beruhigt.
    Ich werde später auch die Einstellungen ausstellen, sofern dies keine negativen Auswirkungen auf meine Skripte haben sollte.


    Danke an alle!

    3daycliff schrieb:

    PHP selbst keine entsprechende Lücken aufweist


    Ich bin recht frisch mit PHP, zumindest was die selbstaendige nutzung des interpreters angeht. Arbeite mich gerade in WAMPs und LAMPs ein. Welche Funktionen sollte man Grunsatzlich sperren? Was ist da generell noch wichtig?
    And i think to myself... what a wonderfuL World!

    Eddy schrieb:

    3daycliff schrieb:

    PHP selbst keine entsprechende Lücken aufweist


    Ich bin recht frisch mit PHP, zumindest was die selbstaendige nutzung des interpreters angeht. Arbeite mich gerade in WAMPs und LAMPs ein. Welche Funktionen sollte man Grunsatzlich sperren? Was ist da generell noch wichtig?

    In Verbindung mit Datenbanken ist wohl die üblichste Sicherheitslücke die SQL-Injection.
    Man sollte hier mit prepared Statements arbeiten und/oder zumindest die Nutzereingabe immer unschädlich machen.

    Eddy schrieb:

    Welche Funktionen sollte man Grunsatzlich sperren?

    Das hängt davon ab, was du mit PHP so machst. Grundsätzlich sollte der erste Schritt stets sein, Einfallstore beim Programmieren zu vermeiden bzw. verwendete Software auf den aktuellen Stand zu halten. Das Deaktivieren von PHP-Funktionen kommt erst dann zum Tragen, wenn ein Angreifer bereits eine Lücke ausnutzt. Und dann ist es meist schon zu spät, weil er mit den üblichen Funktionen genug Schaden anrichten kann. Außerdem kannst du Funktionen bei normalen preisgünstigen Hostern nicht sperren, weil kein Zugriff auf die php.ini. Aus Administrationssicht ist auch angeraten, die Rechte des Benutzers, unter dem PHP ausgeführt wird, auf ein Minimum herunterzubrechen.
    Wenn du Sachen deaktivieren willst, solltest du dich in erster Linie auf Funktionen konzentrieren, die auf externe Ressourcen zugreifen (Dateisystem, Shell, Netzwerk, ...).

    Eddy schrieb:

    Was ist da generell noch wichtig?

    Zu viel um es aufzulisten. Es gibt ganze Bücher dazu. Die meisten (alle?) Probleme in Punkto Sicherheit beim Programmieren rühren aus der Vermischung von (Benutzer-)Daten und Code (SQL, HTML, JS, PHP, ...). Lese die Dokus zu jeder Funktion, die du verwendest, suche nach best practices, vertraue keinen Daten (von Außerhalb) und gehe stets davon aus, dass alles irgendwie missbraucht werden kann.