whitelist, in_array, $_GET unverständlich
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
arbeit
array
break
code
datei
einbinden
frage
impressum
index
info
jemand
kontakt
list
login
ordner
pfad
sinn
switch
unterschiedlichen ordnern
url
-
Hallo,
solange meine Webseite noch aus ein paar Dateien besteht, wollte ich mich mal direkt mit dem Thema Sicherheit befassen um Angriffe gleich vermeiden zu können.
Ein Teil des Aufbaus meiner Seite:
[Home]
->index.php
[includes](im [Home]-Ordner)
->top.php
->main.php
[info](im [includes]-Ordner)
->Impressum.php
->Kontakt.php
Der Grundgedanke ist folgender:
In der index.php sind mehrere bereiche (top, mitte, fuss...)
In der mitte findet der interessante teil statt:
Hier soll als standart die "main.php" included werden. Bei klick auf einen link wird hier "impressum.php" included und bei Kontakt die "Kontakt.php" usw.
Bisher hatte ich das ganze mit switch case gemacht
switch(htmlspecialchars($_GET["index"])){ case "imp": include "includes/info/Impressum.php"; break; case "kont": include "includes/info/Kontakt.php"; break; default : include "includes/main.php"; break; }
Hat ja auch wunderbar geklappt.
Aber mit Whitelists soll man ja die Seite vor fremden includes schützen können.
hier also der code:
$whitelist = array('main', 'Impressum'); if(in_array($_GET['Impressum'], $whitelist)){ include ('includes/info/Impressum.php'); } else if(in_array($_GET['main'], $whitelist)){ include ('includes/main.php'); } else{ echo "Klappt nicht!"; }
Ich habe schon unendlich viele Möglichkeiten ausprobiert. Jedoch wird mir immer wieder "Klappt nicht!" ausgegeben.
Hinzu kommt noch, dass ich nicht weiß, was ich in den link reinschreiben muss, damit auch wirklich ($_GET['Impressum'] oder $_GET['main'] erkannt wird.
also in den link <a href="HIER REIN">Impressum</a>
Hoffe mir wird hier wie immer gut geholfen,
bin gespannt wo meine Fehler liegen.
MfG, Michl
Beitrag zuletzt geändert: 26.4.2013 22:40:08 von xxxparenjxxx -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Dein Ergebnis wird wahrscheinlich deswegen immer angezeigt, da du die Seite bestimmt nicht mit "seite.tld/?main=main" aufrufst.
Durch den Aufruf "if(in_array($_GET['main'], $whitelist))" fragst du schließlich ab, ob der Wert, der in der $_GET-Variable unter dem Index "main" gespeichert ist in der $whitelist vorhanden ist.
Die Variante mit dem switch sollte eigentlich ausreichen und erlaubt auch nicht, dass jemand etwas Fremdes einfügen kann, da du manuell in der Fallunterscheidung die Pfade angibst. -
Hey,
danke für deine Antwort.
Wie schaffe ich den die main so aufzurufen, wie du es beschrieben hast? ( "seite.tld/?main=main" )
Ja das mit dem switch habe ich mir auch gedacht dass es ausreichen sollte, aber in diversen Tutorials und Foren wird die whitelist so sehr gelobt, dass ich mir dachte die sei sicherer...
So ich habe es eben ausprobiert:
wenn ich auf die startseite gehe und an "www.lima-city.de" ein "/?main=main" anhänge bekomme ich die startseite angezeigt, bei "/?Impressum=Impressum" die impressumseite.
Jetzt ist also nurnoch die Frage wie ich "/?main=main" als standart angehängt bekomme, und mich interessiert warum da "/?main=main" stehen muss und nicht einfach "main", denn damit
prüfe ich ja im Grunde ob in dem array $whitelist ein "main" vorhanden ist und ob es in der adresszeile steht (richtig?).(in_array($_GET['main'], $whitelist))
mfg
edit/
Habe jetzt in den link <a herf="?Impressum=Impressum">impressum</a> reingeschrieben. Das klappt schonmal.
Jedoch immernoch die Sache mit dem "main" und dazu kommt noch: auf der main, werden news ausgegeben. diese kann man blättern.
Somit springt er mir beim blättern logischerweise wieder auf "Klappt nicht!" weil in der adresszeile "index.php?news=10" steht.
mfg
Beitrag zuletzt geändert: 27.4.2013 7:57:58 von xxxparenjxxx -
Ich versteh nicht warum du das mit in_array machst. Das ist doch viel zu kompliziert und wie schon gesagt du musst immer bla=bla schreiben. Machs doch einfach so
<?php if (isset($_GET['main'])) { include ('includes/main.php'); } elseif (isset($_GET['impressum'])) { include ('includes/info/Impressum.php'); } else { echo "Klappt nicht"; } ?>
das geht sobal du z.B. "seite.php?main" aufrufst. Der Wert der dann in main steht ist dafür irrelevant
Beitrag zuletzt geändert: 27.4.2013 10:12:11 von jam00 -
So ein ähnliches Projekt gab es schon mal. Da ging es zwar um ein Frameset und nicht um includes, aber das Prinzip ist das selbe. Ich hatte das auf folgende Weise gelöst:
<?php $seite = $_GET['seite']; if ($seite == "") {header('Location: index.php?seite=welcome');}; if ($seite == "impressum" || $seite == "sitemap" || $seite == "hyperlinks" || $seite == "rules" || $seite == "chat-security" || $seite == "kontakt" || $seite == "faq" || $seite == "register-security" || $seite == "members" || $seite == "post-security" || $seite == "articles" || $seite == "calendar" || $seite == "welcome") { $site = $seite.".html";} else {header('Location: index.php?seite=welcome');}; ?>
Das bräuchte ja nur dahingehend modifiziert werden, dass includet wird.
Hier gehts zum Thread, und dort ist die Testseite.
Könnt ja mal auf Schwächen prüfen ^^ ;)
Beitrag zuletzt geändert: 27.4.2013 13:32:53 von menschle -
Oder du benutzt einfach alternativ deinen eigenen Quelltext, den du einfach dahingehend modifizierst:
$whitelist = array('main', 'Impressum'); if(isset($_GET['index']) && in_array($_GET['index'], $whitelist)){ include ('includes/info/'.$_GET["index"].'.php'); } else{ echo "Klappt nicht!"; }
Übergabe erfolgt dann zum Beispiel so:
<a href="includeSeite.php?index=main">Home</a>
oder so
<a href="includeSeite.php?index=Impressum">Impressum</a>
jam00 schrieb:
Ich versteh nicht warum du das mit in_array machst. Das ist doch viel zu kompliziert und wie schon gesagt du musst immer bla=bla schreiben.
1. Weil du vielleicht mehr als 1 Seite einbinden möchtest und nicht alle einzeln aufrufen willst, sondern die Möglichkeiten lieber zentral sammelst
2. Weil das mit bla=bla ziemlich unsinnig ist, weil du dann im GET-Array lauter Feldeinträge für nichts anlegst. Nicht das Speicher nicht günstig wäre, aber muss ja nicht sein....
Beitrag zuletzt geändert: 27.4.2013 12:54:27 von alphara -
alphara schrieb:1. Weil du vielleicht mehr als 1 Seite einbinden möchtest und nicht alle einzeln aufrufen willst, sondern die Möglichkeiten lieber zentral sammelst
2. Weil das mit bla=bla ziemlich unsinnig ist, weil du dann im GET-Array lauter Feldeinträge für nichts anlegst. Nicht das Speicher nicht günstig wäre, aber muss ja nicht sein....
1. Super was bringt dir das wenn du es doch wieder in jeder If schreiben musst? Ist nur mehr Arbeit und total sinnlos!
2. Ich habe doch geschrieben das es Sinnlos ist!
Zu 1. Mein Codevorschlag wenn dies denn gewünscht ist:
<?php $sites = array( "main" => "./includes/main.php", "impressum" => "./includes/info/Impressum.php" ); $suc = false; foreach ($sites as $key => $value) { if (isset($_GET[$key])) { include ($_GET[$key]); $suc = true; break; } } if (!$suc) { echo "Klappt nicht!"; } ?>
Beitrag zuletzt geändert: 27.4.2013 13:22:26 von jam00 -
jam00 schrieb:
alphara schrieb:1. Weil du vielleicht mehr als 1 Seite einbinden möchtest und nicht alle einzeln aufrufen willst, sondern die Möglichkeiten lieber zentral sammelst
2. Weil das mit bla=bla ziemlich unsinnig ist, weil du dann im GET-Array lauter Feldeinträge für nichts anlegst. Nicht das Speicher nicht günstig wäre, aber muss ja nicht sein....
1. Super was bringt dir das wenn du es doch wieder in jeder If schreiben musst? Ist nur mehr Arbeit und total sinnlos!
2. Ich habe doch geschrieben das es Sinnlos ist!
Zu 1. Mein Codevorschlag wenn dies denn gewünscht ist:
<?php $sites = array( "main" => "./includes/main.php", "impressum" => "./includes/info/Impressum.php" ); $suc = false; foreach ($sites as $key => $value) { if (isset($_GET[$key])) { include ($_GET[$key]); $suc = true; break; } } if (!$suc) { echo "Klappt nicht!"; } ?>
Ruhig, brauner, nicht gleich bissig werden.
Nebenbei bemerkt brauche ich insgesammt genau 1 if-Anweisung, egal wieviele Seiten ich habe und du legst in deinem Quellcode ja plötzlich auch einen Array an (und dabei hattest du doch genau da gesagt, dass das unnötig ist)... Vielleicht habe ich deine Frage falsch verstanden, aber du machst jetzt fast das gleiche wie ich nur mit doppelt so viel Quellcode und mit einem n mal so großen GET-Array, wobei n die Anzahl der Seiten ist, die includet werden sollen. Daher fand ich das nicht Sinnlos, es macht ja Sinn, ich finde nur, dass es besser geht....
€dit: Nebenbei fällt mir noch auf, dass dein Code in O(n) läuft und meiner in O(1) [zugegeben, im besten Fall, je nach dem wie schnell in_Array ist], was mich vermuten lässt, dass ich besser meinen eigenen Code verwende....
Beitrag zuletzt geändert: 27.4.2013 14:15:36 von alphara -
Hi,
supergeile Vorschläge :) vielen Dank.
jetzt ist halt das problem dass ich den inhalt von "index" in unterschiedlichen Ordnern aufbewahre (wegen der übersicht).
Folgender code jetzt also:
$whitelist = array('Impressum', 'Kontakt', 'main'); if(isset($_GET['index']) && in_array($_GET['index'], $whitelist)){ include ('includes/info/'.$_GET["index"].'.php'); } else if(isset($_GET['index']) && in_array($_GET['index'], $whitelist)){ include ('includes/'.$_GET["index"].'.php'); // hier soll die main.php included werden da sie einen Ordner drüber liegt }
Der -else if- Teil funktioniert nicht. Logischerweise, weil der ja "index" findet in der ersten Abfrage.
2 Fragen jetzt:
1. Verstehe ich das jetzt so richtig was diese Abfrage bewirkt, also wie das verarbeitet wird?:
Es wird abgefragt ob in der Adresszeile "index" existiert. Danach wird geprüft, ob das was hinter "index" steht also ob "Impressum" von "index=Impressum" aus der Adresszeile in der Whitelist steht. Wann true, wird das included was dem index in der adresszeile gleichgesetzt ist. Habe ich das so richtig verstanden?
2. Kann man so eine Abfrage Ordnerübergreifend gestalten oder wäre das wieder zu unsicher bzw. zu kompliziert und man sollte lieber die Ordnerstruktur überarbeiten und alles was zu "index" included wird bei index einschmeißen usw.?
mfg, Michl
/edit
Wegen der sache mit den Ordner. Nicht dass ihr denkt ich wäre zu bequem einfach main.php in nen andere Ordner reinzuschmeißen. Ich hab noch andere Ordner wie, z.b. login usw. von da werden auch Dateien included. Deswegen ist es für mich interessant zu wissen ob sowas sinnfoll ist oder eher unnütze Penibelheit (gibts das Wort überhaupt oO)?
//edit2
Hat mich zwar Kopfzerbrechen gekostet, aber deshalb lerne ich es ja noch :)
Habe es geschafft, den code so umzuformen dass ich unterschiedliche Dateien aus unterschiedlichen Ordnern einfügen kann.
Hier ist mein Beispiel:
$list= array('Impressum', 'Kontakt', 'Login'); $datei= $_GET["pfad"].'.php'; if(isset($_GET['pfad']) && in_array($_GET['pfad'], $list)){ // Whitelist Prüfung if(file_exists('includes/info/'.$datei)){ // ob die Datei im Ordner existiert include ('includes/info/'.$datei); // Einfügen der existierenden Datei } else if(file_exists('includes/login/'.$datei)){ include ('includes/login/'.$datei); } else{ echo "Datei existiert nicht!"; } } else{ include ('includes/main.php'); }
Das sollte jetzt sicher vor fremden includes sein. Wenn ich irgendwo eine Lücke habe bitte um einen Hinweis.
Ansonstan vielen Dank für die sehr hilfreichen Kommentare, ohne euch wäre ich nie drauf gekommen wie man die whitelist überhaupt benutzt :)
mfg, Michl
Beitrag zuletzt geändert: 28.4.2013 0:17:42 von xxxparenjxxx -
1. Ja hast du richtig verstanden
2. Ja deine möglichkeit kannst du nutzen (ich aber finde file_exist nicht seh elegant und es ist ziemlich langsam) oder den Code den ich oben schon gepostet habe, da hatte ich das nämlich schon eingebaut. Da steht der Pfad für die Datei mit im Array.
@alphara
Ruhig, brauner, nicht gleich bissig werden.
Das kannst du dir beim nächsten mal spaaren
Aber du hast recht mit deiner If-Anweißung, ich habe deinen Code falsch gelesen :( dumm von mir
Ein Array braucht man dann wenn man es Zentral regeln will. Dann halte ich nicht das Array für unnötig, das braucht man dafür natürlich ich find nur das "Zentral" regeln unnötig. Aber wenn er das so will soll er es so machen.
Aber ich verstehe nicht warum mein GET-Array größer sein soll. Eig ist es ja kleiner da du nicht z.B. page.php?index=impressum sondern nur page.php?impressum eingeben musst.
Meintest du mein sites-Array? Da hast du recht das ist größer aber nur weil ich das Problem bei ihm gleich gesehen habe das die Seiten in unterschiedlichen Ordnern sind und habe dies direkt behandelt. Das kann man aber auch rauslassen dann ist das Array nicht größer.
Allem in Allem,
Wenn du es jetzt noch schaffst bei deinem Code ohne soetwas wie file_exist einzubauen das die Datein in unterschiedlichen Ordnern sind und er weiterhin kurz und elegant bleibt dann gebe ich mich geschlagen ;) -
jam00 schrieb:
Allem in Allem,
Wenn du es jetzt noch schaffst bei deinem Code ohne soetwas wie file_exist einzubauen das die Datein in unterschiedlichen Ordnern sind und er weiterhin kurz und elegant bleibt dann gebe ich mich geschlagen ;)
Herausforderung angenommen ;)
hehe
Und es hat sogar geklappt.
Ist es aber immernoch sicher genugß oder sind dadurch jetzt Sicherheitslücken aufgetreten? (Sollten ja eigentlich nicht.)
Es wird jetzt nicht mehr geprüft ob die Datei in einem Ordner existiert aber es wird ja immernoch der Whitelist geprüft.
$list = array('main', 'Impressum', 'Kontakt', 'login'); $datei= $_GET["pfad"].'.php'; if(isset($_GET['pfad']) && in_array($_GET['pfad'], $list)){ switch($datei){ case "Impressum.php": include ('includes/info/'.$datei); break; case "Kontakt.php": include ('includes/info/'.$datei); break; case "login.php": include ('includes/member/'.$datei); break; } } else{ include ('includes/main.php'); }
Ich glaube aber wenn es jemand schafft, eine Datei in einen Ordner einzuschleusen in dem sie noch nicht existiert (da es ja ordnerübergreifend geschieht) und diese Datei so umbenennt dass sie so heißt wie in einem anderen Ordner, in dem auch Dateien geprüft werden, dan könnte er trotzdem includes einschleusen.
Aber wie wahrscheinlich ist sowas? bzw Wie schwer/einfach ist sowas zu machen?
mfg, michl -
Dazu gab es doch schon mal vor Ewigkeiten ein Thema … eventuell hilft euch das ja weiter.
-
@xxxparenjxxx
Ja aber jetzt behandelst du die Seiten doch nicht mehr Zentral und musst für jede eine einzelne Case-Anweißung machen. Da finde ich meine Lösung doch noch etwas eleganter!
xxxparenjxxx schrieb:
Ich glaube aber wenn es jemand schafft, eine Datei in einen Ordner einzuschleusen in dem sie noch nicht existiert (da es ja ordnerübergreifend geschieht) und diese Datei so umbenennt dass sie so heißt wie in einem anderen Ordner, in dem auch Dateien geprüft werden, dan könnte er trotzdem includes einschleusen.
Aber wie wahrscheinlich ist sowas? bzw Wie schwer/einfach ist sowas zu machen?
Naja aber wenn sich jemand so viele Rechte auf einem Server verschaffen kann wird er wohl kaum noch eine "Lücke" in einem Include benötigen
Beitrag zuletzt geändert: 28.4.2013 14:45:37 von jam00 -
jam00 schrieb:
Ja aber jetzt behandelst du die Seiten doch nicht mehr Zentral und musst für jede eine einzelne Case-Anweißung machen. Da finde ich meine Lösung doch noch etwas eleganter!
Naja aber wenn sich jemand so viele Rechte auf einem Server verschaffen kann wird er wohl kaum noch eine "Lücke" in einem Include benötigen
Hast recht, du hast das die Dateipfade auch in ein array gepackt.
Bei mir ist es halt so, dass ich bis jetzt nicht mehr als diese paar Dateien habe die über die index.php laufen also in der index.php included werden.
Die main.php ist nämlich ein news-bereich in dem man Seiten blättern kann (da werden dan die Parameter auch per $_GET übergeben. Da steht dan sowas wie "index.php?news=10").
Wenn ich main.php genauso einbinde wie auch die "Impressum.php" dann kann ich nicht mehr blettern. (k.P. wie ich das dan hinbekomme...)
Hab nämlich auch ein Gästebuch, in dem man auch blättern kann, da ist dan die Übergabe auch per $_GET "Gaestebuch.php?gb=10" usw.
Wenn das aber so klappen würde, dass man blättern kann, trotz dass die Dateien über die whitelist eingebunden sind, dan wäre dein Beispiel mit dem array natürlich immens von nutzen, denn dan hätte ich nur eine einzige Datei, in die ich alle anderen einbinden könnte.
Werde mir jetzt mal den Verweis von hackyourlife anschauen. Mal schauen ob da was nützliches zu finden ist. Ich werde dan wieder posten wenn ich eine Lösung habe.
Danke euch soweit erstmal :)
mfg
//EDIT
Hallo,
habe es endlich geschafft.
Habe den Code von jam00 verwendet, etwas verändert und schon hats geklappt.
Es ist halt wie jedes mal. Man Sucht, und versucht. Aber am ende ist es doch eine einfache Lösung....
Die Dateien werden alle mit dem jeweiligen pfad in einem array gespeichert und mit einer foreach schleife abgefragt.
Vorher wird noch geprüft ob der jeweilige key in der whitelist enthalten ist.
Ich denke mal das sollte Sicherheit genug sein was das Einbinden des Inhalts angeht...
Hier der Code:
$sites = array( "main" => 'includes/main.php', "Gaestebuch" => "includes/Gaestebuch.php", "Impressum" => "includes/info/Impressum.php", "Kontakt" => "includes/info/Kontakt.php", ); $list = array('main', 'Gaestebuch', 'Impressum', 'Gaestebuch''); $suc = false; foreach ($sites as $key => $value) { if (isset($_GET[$key]) && in_array($key, $list)) { include ($value); $suc = true; break; } } if (!$suc) { echo "Kein Zugang!"; }
Vielen Dank an alle die geholfen haben :)
mfg, michl
Beitrag zuletzt geändert: 28.4.2013 22:50:35 von xxxparenjxxx -
Oh ich hab mir gerade nochmal meinen Code angeschaut und gemerkt, dass er einen Fehler hat!
<?php $sites = array( "main" => "./includes/main.php", "impressum" => "./includes/info/Impressum.php" ); $suc = false; foreach ($sites as $key => $value) { if (isset($_GET[$key])) { include ($value); $suc = true; break; } } if (!$suc) { echo "Klappt nicht!"; } ?>
Hattest du ja schon gemerkt wollte es trotzdem noch richtig stellen.
Ich kann aber keinen Sinn erkennen bei deinem Code warum du nochmal $list und in_array benutzt ist doch überflüssig. -
jam00 schrieb:
Ich kann aber keinen Sinn erkennen bei deinem Code warum du nochmal $list und in_array benutzt ist doch überflüssig.
Ich bin halt seit tagen am Lesen, was die Sicherheitslücken von Webseiten angeht und bin dadurch etwas paranoid geworden was das betrifft.
Es befinden sich zwar keine Wichtigen Kundendaten oder solchen Sachen auf der Homepage die ich erstelle, aber dennoch ist es für mich wichtig es so sicher wie möglich zu gestalten.
Eine doppelte Absicherung hat noch niemandem geschadet denke ich, zumal das ja nicht viel Arbeit ist einen String in ein zweites Array einzufügen, welches direkt untendrunter geschrieben ist...
Was deinen Fehler angeht, ja ich habe den "gefunden", musste aber erst n paar Minuten ausprobieren, da ich mit foreach-schleifen noch garnichts gemacht hatte vorher xD
In jedem Fall nochmal vielen Dank für die Hilfe, jetzt binn ich um einiges schlauer geworden :)
mfg, michl -
Gern geschehen!
Aber ich denke eine doppelte Absicherung macht hier keinen Sinn. Die meisten Sicherheitslücken in Webseiten entstehen durch Unachtsamkeit (Sieht man ja an dem Code den ich gepostet hatte)! Bei dem kurzen Code allerdings ist es schwer etwas zu vergessen wenn man darauf achtet und sich ein wenig Zeit nimmt drüber nach zu denken. Wenn du etwas doppelt machst bringt dir das eig. nichts vor allem kannst du das bei großen Seite nicht machen, da geht einfach zu viel Performance verloren!
Weiterhin ist bei meinem Code keine Lücke drin denn mit der Berichtigung wird keinerlei Eingabe vom Benutzer direkt weiter verwendet, es wird lediglich geguckt ob zu dem was in der Adressleiste ist ein Eintrag existiert, ist dies der Fall werden ab da nur noch Infos aus dem Array verwendet. Es ist sozusagen Passiv ;) -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage