kostenloser Webspace werbefrei: lima-city


php-include-Befehl sicher machen?

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    replikator

    replikator hat kostenlosen Webspace.

    Guten Tag,
    ich hoffe man kann mir hier weiterhelfen. Und zwar suche ich eine Lösung wie man sicher php-Datein mit einen include-Befehl einbinden kann.

    Soll wie folgt funktionieren.

    index.php -> hier ist praktisch das komplette Layout (CSS, Javascripte ect.) schon fertig und mehr oder weniger ohne Content...

    nun kommen eben die "Content-Seiten" hinzu z.B.

    - kontakt.php
    - ueber_uns.php
    - unterseite1.php
    - unterseite2.php

    ect...

    es soll eben recht einfach gehalten werden.... die ganzen einzelnen Unterseiten sollen nun in die index.php included werden....

    jetzt habe ich hier im Forum gelesen das man den Befehl "include($_GET['page']);" man nicht verwenden soll. Kann mir einer ein Beispiel zeigen wie man sicher php-Datein einfügen kann?
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    Einfache unschöne Möglichkeit:
    <?php
    $pages = array(
        'kontakt' => 'kontakt.php',
        'about' => 'ueber_uns.php'
    // für alle weiteren Seiten gilt das gleiche Schema:
    // 'name in der url' => 'php-seite.php'
    );
    $page = $_GET['page'];
    if(!isset($pages[$page])) {
        die('Die angeforderte Seite wurde nicht gefunden: '.htmlentities($page));
    }
    include($pages[$page]);
    ?>
    Wenn die seite jetzt mit
    index.php?page=about
    aufgerufen wird wird ueber_uns.php includiert.
  4. $_GET['page'] kannst Du verwenden. Die vom User manipulierbaren Daten sollten nur nicht direkt für das include verwendet werden.

    So z.B. ist es problemlos möglich:
    switch ($_GET['page']) {
        case 'kontakt':
            include 'kontakt.php';
            break;
        case 'ueber_uns':
            include 'ueber_uns.php';;
            break;
        case 'unterseite1':
            include 'unterseite1.php';;
            break;
        case 'unterseite2':
            include 'unterseite2.php';;
            break;
       default:
            include 'startseite.php'    // diese Seite laden, wenn keine andere zutreffend ist.
            break;
    }
  5. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    fatfreddy schrieb:
    $_GET['page'] kannst Du verwenden. Die vom User manipulierbaren Daten sollten nur nicht direkt für das include verwendet werden.
    Dein Code ist ziemlich genau das gleiche was ich schon beschrieben habe.
  6. hackyourlife schrieb:
    Dein Code ist ziemlich genau das gleiche was ich schon beschrieben habe.

    Wenn schon, dann müßte es heißen: Er bewirkt das Gleiche! :wink:

    Was aber nicht ganz stimmt. Besonders unsere Vorschläge bezügl. Fehlerbehandlung sind unterschiedlich.
    Du läßt das Script einfach sterben, wenn keine passende Seite gefunden wurde,Für den User nicht unbedingt prickelnd! Meinereiner leitet dann auf eine, zu definierende, Startseite weiter. Ist aber nicht unbedingt das Gelbe vom Ei, da dann noch der Hinweis fehlt, daß die angeforderte Seite nicht existiert. Dieses könnte aber mit einer kleinen Änderung umgangen werden.




    Beitrag zuletzt geändert: 1.1.2012 22:49:12 von fatfreddy
  7. Autor dieses Themas

    replikator

    replikator hat kostenlosen Webspace.

    Hey Danke ihr beiden!
    Wenn ich das also richtig verstehe muss ich dann mehr oder weniger eine "Liste" mit all meinen php-Datein (Content-Seiten) erstellen und auch dementsprechend aktuell halten....

    Ist folgendes möglich bzw. "sicher"?

    In der "index.php" die php-Dateiliste ganz einfach einbinden mit:
    <?php
    include("content.php");
    ?>


    Dann bleibt die index.php unberührt, und die "content.php" wäre immer zu ändern.
  8. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    replikator schrieb:
    Hey Danke ihr beiden!
    Wenn ich das also richtig verstehe muss ich dann mehr oder weniger eine "Liste" mit all meinen php-Datein (Content-Seiten) erstellen und auch dementsprechend aktuell halten....
    Das musst du deshalb machen dass nicht irgend eine Datei includiert wird die gar nicht für den User sichtbar sein sollte (z.B. .htaccess-Dateien).

    replikator schrieb:
    Ist folgendes möglich bzw. "sicher"?

    In der "index.php" die php-Dateiliste ganz einfach einbinden mit:
    <?php
    include("content.php");
    ?>


    Dann bleibt die index.php unberührt, und die "content.php" wäre immer zu ändern.
    Ist eine gute Idee, dann musst du nur noch eine Datei ändern die nur die Liste beinhaltet.
    Sicher ist das auch, er werden ja keine Benutereingaben an include übergeben.
  9. Ich hab mir mal dafür in ner Datenbank ne Tabelle angelegt in der zu dem Key ein Pfad zugeordnet ist und der einfach anhand des Keys den Pfad aus der datenbank zieht, kann ich dir auch mal schicken falls du willst.

    Der Vorteil ist, dass das am leichtesten zu Pflegen ist, weil du nie wieder an dem Code was ändern musst, sondern nur noch ne Zeile in der Datenbank einfügen musst.
  10. Autor dieses Themas

    replikator

    replikator hat kostenlosen Webspace.

    Dankeschön! Ich werd jetzt mal die Sachen konkret ausprobieren wie ich zurecht komme und ob das auch so funktioniert XD ... kann also sein das ich später noch die ein oder andere Frage dazu habe ....
  11. die Sache ist die:

    man soll nicht $_GET['page'] direkt verwenden, weil so jede User-Eingabe direkt im Script ankommt.

    besser:
    die Eingabe aus $_GET['page'] escapen und Steuerzeichen (und Sonderzeichen, etc.) entfernen
    und dann mit der "gesäuberten" Variable weiter arbeiten

    hier male ein Beispiel (sicher nicht komplett 100% sicher)

    if (!empty($_GET['page'])) { 
    $run_page = trim(chop($_GET['page'])); 
    $run_page = strip_tags($run_page); 
    
    $suche = array( "\r", "\n", "\s", "\t", "\$", "\"", "%" ); 
    $ersetze = array( "",  "",  "",  "",  "",  "",  "" ); 
    
    $run_page = str_replace($suche,  $ersetze, $run_page); 
    
    $run_page = htmlentities($run_page); 
    $run_page = stripslashes($run_page); 
    }
    
    $myincludefile = "seiten/".$run_page.".php"; 
    
    if (file_exists($myincludefile)) { 
    include($myincludefile); 
    }


    man kann auch mit einem regex nur bestimmte Zeichen zulassen

    Bsp: nur erlaubt: Buchstaben, Zahlen, Unterstrich und Minus

    $run_page = preg_replace('/[^0-9A-Za-z_-]/', '', $_GET['page']);

    so wird alles, was nicht im Pattern definiert ist, einfach entfernt (ersetzt durch '' Leerstring)






    Beitrag zuletzt geändert: 7.1.2012 11:08:12 von tauli
  12. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    tauli schrieb:
    die Sache ist die:

    man soll nicht $_GET['page'] direkt verwenden, weil so jede User-Eingabe direkt im Script ankommt.

    besser:
    die Eingabe aus $_GET['page'] escapen und Steuerzeichen (und Sonderzeichen, etc.) entfernen
    und dann mit der "gesäuberten" Variable weiter arbeiten

    hier male ein Beispiel (sicher nicht komplett 100% sicher)

    if (!empty($_GET['page'])) { 
    $run_page = trim(chop($_GET['page'])); 
    $run_page = strip_tags($run_page); 
    
    $suche = array( "\r", "\n", "\s", "\t", "\$", "\"", "%" ); 
    $ersetze = array( "",  "",  "",  "",  "",  "",  "" ); 
    
    $run_page = str_replace($suche,  $ersetze, $run_page); 
    
    $run_page = htmlentities($run_page); 
    $run_page = stripslashes($run_page); 
    }
    
    $myincludefile = "seiten/".$run_page.".php"; 
    
    if (file_exists($myincludefile)) { 
    include($myincludefile); 
    }


    man kann auch mit einem regex nur bestimmte Zeichen zulassen

    Bsp: nur erlaubt: Buchstaben, Zahlen, Unterstrich und Minus

    $run_page = preg_replace('/[^0-9A-Za-z_-]/', '', $_GET['page']);

    so wird alles, was nicht im Pattern definiert ist, einfach entfernt (ersetzt durch '' Leerstring)
    Nachdem es hier nicht um die Weiterverarbeitung von Parametern (z.B. in eine Datenbank eintragen) geht, ist auch das von dir vorgeschlagene riskant.

    Etwas zu deinem Code: htmlentities hat in Verbindung mit Dateinamen gar nichts verloren! Du speicherst ja auch keine Datei unter dem Namen &amp;Datei.txt (was übrigens auf manchen Dateisystemen gar nicht zulässig ist)!


    Noch etwas ist in deinem Code ungünstig: "/" wird nicht gefiltert! Damit ist es möglich Dateien wie seiten/../index.php auszugeben.

    Es gab mal (ich weiß nicht ob es das immer noch gibt) einen Bug (Poisonous-Null-Byte): ein %00 in einer URL entspricht einem \0-Byte in PHP. In C ist ein \0-Byte das String-Ende-Zeichen. Nachdem PHP in C programmiert ist war folgendes möglich:
    include("datei\0.php");
    resultiert im Einbinden von "datei". Das .php fällt weg, weil vorher der String terminiert wird (mit \0).
    hier nachlesen
    Wie gesagt, ich weiß nicht ob das noch funktioniert!

    Hier ist das genau beschrieben mit "sicherem" include

    Edit: auf lima-city funktioniert Poisonous-Null-Byte nicht.

    Beitrag zuletzt geändert: 7.1.2012 12:39:44 von hackyourlife
  13. ja, hast recht, htmlentities() ist hier eher überflüssig
    bei Datei include würde sich - wennüberhaupt - evtl eher das Gegenteil anbieten
    also html_entity_decode() ... um aaus b&uuml;cer das Wort bücher zu machen ... aber eigentlich auch Quatsch.
    eher noch url_decode() ... wenn von _GET


    es sollte ja nur ein Beispiel sein, keine Lösung. steht ja drüber, das es nicht 100% sicher ist

    und ich wollte halt grundsätlich mal auf das escapen
    und Steuer-/Sonder-Zeichen entfernen bei User-Eingabe hinweisen

    im Grunde genügt es ja so wie oben mit der switch - case Variante
    aber dann muss man halt bei neuen Dateien (Seiten) diese switch - case auch "pflegen" bzw anpassen
    mit der anderen Variante kann man halt beliebig neue Seiten anlegen ohne diese Anpassung.


    wer doch filtern will, kann das Suchen und Ersetzen der Steuer-/sonderzeichen
    ja ganz einfach um ein "/" ... und evtl noch andere "Zeichen" erweitern ...

    Beispiel
    if (!empty($_GET['page'])) { 
    $run_page = trim(chop($_GET['page'])); 
    $run_page = strip_tags($run_page); 
    $run_page = url_decode($run_page); 
    
    $suche   = array( "\r", "\n", "\s", "\t", "\$", "\"", "%", "/", "?", "&", "'", "\0" ); 
    $ersetze = array( "",   "",   "",   "",   "",   "",   "",  "",  "",  "",  "",  "" ); 
    
    $run_page = str_replace($suche, $ersetze, $run_page); 
    
    $run_page = stripslashes($run_page); 
    }
    
    $myincludefile = "seiten/".$run_page.".php"; 
    
    if (file_exists($myincludefile)) { 
    include($myincludefile); 
    }


    oder eben mit preg_replace() nur erlaubte Zeichen im String lassen.

    nochwas ein Hinweis zu sicherm include ...

    wenn eine Datei nur dann includet werden soll, wenn der User sich eingeloggt hat,
    dann sollte auch innerhalb der zu includierten Datei eine Abfrage sein,
    die prüft, ob der Login "aktiv" bzw. "gültig" ist ... z.B. mit SESSION oder COOKIE
    .. aber das ist auch wieder anderes Thema ...
    :)


    EDIT:

    ok, sehe ein das mein Vorschlag eher suboptimal ist,
    alle Zeichen raus filtern die "gefährlich" sein könnten ist viel zu viel Aufwand
    auch weil man ja zudem an HEX Zeichen und so denken müsste

    also ist das mit Switch - Case doch das beste, mit wenigstem Aufwand
    und viele neue Seiten wird man ja nicht öfter haben, wegen Anpassung
    zur Not macht man halt eine kleine Datenbank oder csv
    mit den Werten, bei welcher Eingabe welche Datei includet wird

    ^O^


    Beitrag zuletzt geändert: 7.1.2012 13:07:50 von tauli
  14. Ja, und im endeffekt müsste man entweder drauf achten, ob da nix liegt,
    auf das nicht zugegriffen werden soll,
    oder man überprüft ob das erlaubt ist.
    Dann wäre es ja wieder ein switch case.

    Ich würde generell nie direkt mit den Daten vom User arbeiten.

    Heisst beim zugriff aufs Dateisystem
    Schlüsselwörter mit switch case

    und bei Datenbanken
    strings escapen, wenns nicht anders geht

    Beitrag zuletzt geändert: 7.1.2012 13:24:11 von sadweb
  15. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    tauli schrieb:
    ja, hast recht, htmlentities() ist hier eher überflüssig
    bei Datei include würde sich - wennüberhaupt - evtl eher das Gegenteil anbieten
    also html_entity_decode() ... um aaus b&uuml;cer das Wort bücher zu machen ... aber eigentlich auch Quatsch.
    eher noch url_decode() ... wenn von _GET
    AUUUUU!!!
    url_decode sollst du NIEMALS auf $_GET-Variablen anwenden.
    $_GET wird automatisch urldecodet!

    hackyourlife schrieb:
    Einfache unschöne Möglichkeit:
    <?php
    $pages = array(
        'kontakt' => 'kontakt.php',
        'about' => 'ueber_uns.php'
    // für alle weiteren Seiten gilt das gleiche Schema:
    // 'name in der url' => 'php-seite.php'
    );
    $page = $_GET['page'];
    if(!isset($pages[$page])) {
        die('Die angeforderte Seite wurde nicht gefunden: '.htmlentities($page));
    }
    include($pages[$page]);
    ?>
    Wenn die seite jetzt mit
    index.php?page=about
    aufgerufen wird wird ueber_uns.php includiert.
    Nach den anderen Vorschlägen finde ich das immer noch am besten und einfachsten zu warten. Das Array $pages würde ich in einer externen Datei speichern. ;-)
  16. hackyourlife schrieb:
    Nach den anderen Vorschlägen finde ich das immer noch am besten und einfachsten zu warten. Das Array $pages würde ich in einer externen Datei speichern. ;-)

    Richtig! Zumindest wenn man das DIE() noch durch eine sinnvolle Fehlerbehandlung ersetzt, die den User nicht blöd dastehen läßt.

    Gegenüber meiner Switchlösung gäbe es sogar noch einen zweiten Vorteil. Aus dem Array ließe sich, mit wenig Aufwand, auch gleich noch eine Seitennavigation generieren. :wink:

    FF

    Beitrag zuletzt geändert: 7.1.2012 14:04:12 von fatfreddy
  17. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    fatfreddy schrieb:
    Zumindest wenn man das DIE() noch durch eine sinnvolle Fehlerbehandlung ersetzt, die den User nicht blöd dastehen läßt.
    Ich würde statt
    die()
    folgendes verwenden:
    include('error.php');
    exit();


    fatfreddy schrieb:
    Gegenüber meiner Switchlösung gäbe es sogar noch einen zweiten Vorteil. Aus dem Array ließe sich, mit wenig Aufwand, auch gleich noch eine Seitennavigation generieren. :wink:
    Hat noch einen Vorteil (aber erst bei mehreren (hundert) Dateien die zur Auswahl stehen): ein Zugriff auf eine Hashtable ist schneller als wiederholte strcmp (was indirekt bei case passiert).
  18. Wie wär's damit?

    <?php
    
    class Page {
      static private $pages = array ('kontakt', 'ueber_uns');
    
      const DEFAULT_PAGE = 'index';
    
      static public function includePage($page_name) {
        if (!in_array($page_name, self::$pages)) {
          $page_name = self::DEFAULT_PAGE;
        }
        include $_SERVER['DOCUMENT_ROOT'] . '/pages/' . $page_name . '.php';
      }
    }
    
    Page::includePage($_GET['page']);


    Das könnte man noch um eine Fehlerseite erweitern, wenn die Seite zwar im Array steht, die dazugehörige PHP-Datei aber nicht vorhanden ist. Aber da geht natürlich noch einiges mehr :)

    Beitrag zuletzt geändert: 13.1.2012 13:16:43 von fabo
  19. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!