php-include-Befehl sicher machen?
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
arbeiten
array
aufwand
beispiel
break
byte
code
datei
datenbank
einbinden
eingabe
index
kontakt
page
sache
string
suche
switch
url
zeichen
-
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? -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Einfache unschöne Möglichkeit:
Wenn die seite jetzt mit<?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]); ?>
aufgerufen wird wird ueber_uns.php includiert.index.php?page=about
-
$_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; }
-
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!
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 -
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. -
replikator schrieb:
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).
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....
replikator schrieb:
Ist eine gute Idee, dann musst du nur noch eine Datei ändern die nur die Liste beinhaltet.
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.
Sicher ist das auch, er werden ja keine Benutereingaben an include übergeben. -
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. -
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 ....
-
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 -
tauli schrieb:
Nachdem es hier nicht um die Weiterverarbeitung von Parametern (z.B. in eine Datenbank eintragen) geht, ist auch das von dir vorgeschlagene riskant.
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)
Etwas zu deinem Code: htmlentities hat in Verbindung mit Dateinamen gar nichts verloren! Du speicherst ja auch keine Datei unter dem Namen &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:
resultiert im Einbinden von "datei". Das .php fällt weg, weil vorher der String terminiert wird (mit \0).include("datei\0.php");
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 -
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ü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 -
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 -
tauli schrieb:
AUUUUU!!!
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ücer das Wort bücher zu machen ... aber eigentlich auch Quatsch.
eher noch url_decode() ... wenn von _GET
url_decode sollst du NIEMALS auf $_GET-Variablen anwenden.
$_GET wird automatisch urldecodet!
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.
Einfache unschöne Möglichkeit:
Wenn die seite jetzt mit<?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]); ?>
aufgerufen wird wird ueber_uns.php includiert.index.php?page=about
-
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.
FF
Beitrag zuletzt geändert: 7.1.2012 14:04:12 von fatfreddy -
fatfreddy schrieb:
Ich würde statt
Zumindest wenn man das DIE() noch durch eine sinnvolle Fehlerbehandlung ersetzt, die den User nicht blöd dastehen läßt.
folgendes verwenden:die()
include('error.php'); exit();
fatfreddy schrieb:
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).
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. -
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 -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage