Überprüfen auf include()

Hallo wollte das mit der Konstante auch machen aber es klappt nicht.

index.php
PHP:
define("ZUGRIFF",true);
include "inc/config.php";
$link = $_GET["go"];
if (isset($link))
{
  if (is_readable("links/".$link.".php"))
  {
    include "links/".$link.".php";
  }
  else include "links/error.php";
}
else include "links/news.php";

members.php
PHP:
if (ZUGRIFF == true)
{
  // code
}
else include "error.php";
Er führt den Code aus wenn ich von der index.php die members aufrufe sowie bei direktem Aufruf von links/members.php, aber letzteres darf nicht sein.

Thx 4 help
 
Um zu verhindern, dass eine Include-Datei direkt aufgerufen wird, vergleiche ich __FILE__ mit $_SERVER['SCRIPT_FILENAME']. Die "magische" Konstante __FILE__ enthält immer Pfad und Name der Datei, in der sie steht, wohingegen die Super-Globale $_SERVER['SCRIPT_FILENAME'] Pfad und name der Datei enthält, die ursprünglich aufgerufen wurde:

Include-Datei (test_inc.php):
PHP:
<?php
	if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) die('So nicht!');
	echo 'Alles klar!';
?>
Haupt-Datei:
PHP:
<?php
	include './test_inc.php';
?>
Vorsicht: Bei Windows-Servern kommen bei __FILE__ Backslashes als Verzeichnistrenner, bei $_SERVER['SCRIPT_FILENAME'] allerdings Slashes. Hier muss man ein bischen tricksen:
Include-Datei (test_inc.php):
PHP:
<?php
	if (str_replace('\\', '/', __FILE__) == $_SERVER['SCRIPT_FILENAME']) die('So nicht!');
	echo 'Alles klar!';
?>
Im übrigen birgt die Technik, Dateien aufgrund von GET-Variablen einzubinden, die nicht unerhebliche Gefahr, dass der böse User das rausfindet und seine eigenen Includes einschleust...
 
Wenn schon Seiten in der Url übergeben werden.Dann solltes du auch voher den Wert prüfen auf Zeichen wie / oder http:.
Zb: wird übergeben mit ?c=neuseite Fremder_user schreib um auf ?c=htttp://andereseite/hack.php

$site = trim ($_Get['c']);

So dann brauchste nur noch aus der Variable $site die unerwünschten string rausholen.
zbs. Zeichen wie / oder ganze zeichen ketten ( php,http,:,)

Nach dem Filtern hat dann beim Hack_angriff die Variable nur noch den Wert:andereseitehack und damit wird eine ungültiger link aufgerufen.

code:
PHP:
$invalide = array('/','/\/',':','.');
$site = str_replace($invalide,' ',$site);
 
Zuletzt bearbeitet:
splasch:

Blacklists sind in solchen Fällen ein völlig falscher Ansatz, es ist ebenso falsch zu versuchen Einträge zu "berichtigen", wenn die Daten fehlerhaft sind, sollte die Verarbeitung abgebrochen werden (z.B.: durch eine Weiterleitung zur index oder eben eine Fehlermeldung).

Du wirst NIE alle unerlaubten Zeichen rausfiltern können, es gibt so viele Möglichkeiten sie doch unterzuschieben, bestes Beispiel sind UTF8-Kodierungen oder NULL-Bytes. Man sollte in solchen Fällen Whitelists einsetzen.

Für weitere Informationen zum Thema empfehle ich dir das Buch "PHP Sicherheit" von Christopher Kunz, da ist sowas ziemlich gut beschrieben.

Man sollte übrigens auch bei Variablen aus $_SERVER kommen aufpassen, bei weitem nicht alle kommen vom Server, sondern viele sind per Client manipulierbar.

Online Skater:

1. Du übernimmst $link direkt aus $_GET, was Tür und Tor öffnet ...
2. Man sollte immer auch den Typ entsprechend vergleichen, wenn du also "ZUGRIFF === true" machst, gehts auch. Alternativ kannst du mit "defined" testen ob die Konstante definiert ist.


Das war's erstmal :)
 
So, kleiner Nachtrag da gerade die Nachfrage per PN kam, nachfolgend die PN erstmal:

Hallo Sir Robin

Im Thread: "Include überprüfen"
meinst du das ich Tür und Tor öffne weil $link direkt von $_GET übernommen wird. Ich frage mich jetzt wie ich es sicherer machen soll, bzw warum reicht is_readable() nicht aus ?
Auf was sollte ich denn $_GET['go'] überprüfen ?

Danke für dein Verständnis.

Auf was sollst du $_GET['go'] überprüfen? Ganz einfach, wie ich vorher schon schrieb, ist in solchen Fällen sehr wichtig das du überprüfst ob der übergebene Wert gültig ist. Du machst dir also eine Liste, in dem gültige Werte drin stehen und machst daraufhin die Gegenprüfung. Diesen Ansatz nennt man Whitelist. Eine beispielhafte Implementierung ist die folgende:

PHP:
<?php

// das Array mit den erlaubten Seiten
$erlaubteSeiten = array('blog', 'news', 'links', 'kontakt');

if( in_array($_GET['go'], $erlaubteSeiten) ) {
    // ... Zugriff erlaubt, include Seiten
    include('...');
} else {
    // ... nicht erlaubt, 404
    include('404.php');
}
?>

ist natürlich super simpel jetzt, man kann das auch noch anpassen, sodass das Array vielleicht nicht hardcodiert ist, sondern bei dir aus der Datenbank kommt. Oder oder oder, aber es geht ja um den Ansatz.

Der Blacklist-Ansatz wäre der, dass man versucht "böse Zeichen" etc. zu unterbinden, soll heißen: Man sucht nach speziellen Zeichen, und wenn die vorkommen versucht man im schlimmsten Fall diese zu bereinigen (was in solchen Fällen dann gleich 2 Fehler auf einmal wären) oder bricht dann mit einem Fehler ab. Dieses Verfahren hat aber ziemliche Nachteile:

  • sehr hoher Wartungsaufwand, es kommen schließlich immer wieder neue Sachen dazu
  • man übersieht sehr gerne bestimmte Zeichen
  • man vergisst gewisse Sonderbarkeiten, etwa spezielle Kodierungen (UTF8 etc.)
  • wenn man den Bereinigen Weg wählt: Oft Fehler beim Bereinigen die, die Lücken erst aufklaffen lassen

kurzum: Im Vergleich zu einer Blacklist ist das sehr unsicher in diesem Fall. Es gibt wirklich ungemein viel zu beachten um eine sichere Anwendung zu programmieren, aber man erreicht schon eine nicht zu verachtende Grundsicherheit wenn man darauf achtet sinnvoll mit Usereingaben umzugehen.

Es gibt auch viele Servermodule/PHP-Module die die Sicherheit erhöhen, etwa Hardened PHP (zu empfehlen, auch die Bücher von denen), mod_security oder auch eine chroot-PHP-FCGI Umgebung im Apache ... aber all das greift später, man kann sich Sicherheit wie eine Art "Zwiebelschalen"-Modell vorstellen, jede Komponente ist eine Art Schale. Manch eine ist anfälliger als die andere und viele Komponenten spielen mit rein, etwa der Webserver, der Datenbankserver, das Betriebsystem etc., aber einer der wichtigsten Schichten, gerade weil sie die Schnittstelle zwischen Außenwelt in Innenwelt bietet, ist die Applikation als solches und diese sollte man so gut wie möglich absichern, zumal es oftmals gar nicht mal so schwer ist. Um die Kurve zu kriegen: Die letzten Lücken im Bekannten Joomla/Mambo basierten alle darauf, das include-Dateien direkt aufgerufen wurden und es keine ausreichende Überprüfung gab ob es ein direkter Aufruf war oder nicht, was dann zusammen mit register_globals zur Lücke führte. Die haben übrigens mittlerweile auch überall eine Variable drin, die angibt ob die Datei includet ist oder nicht. Eine Konstante eignet sich in dem Fall trotzdem besser.

Puh, ganz schön ausgeholt, hoffe es wurde ausreichend dargelegt was ich meinte, wenn nicht frag nochmal nach.
 
Boah suppi danke für die ausfühliche Erklärung macht echt Spass immer wieder was dazu zu lernen ;)

Dann mache ich das mit der Whitelist :-)
Vielen Dank Robin Hood ;-]
 
Bei mir ist das so gelöst, dass ich das Menü der Seite in einer MySQL DB hab.
Weil ich später über ein Adminpanel das Menü so über ein Webfrontend editieren kann.

Die Whitelist existiert somit bereits.

Jetzt werde ich beim includen des entsprechenden PHP Files in diesem Fall nochmals überprüfen, ob dies auch in der Menü DB steht :)

Vielen Dank
An diesen Sicherheitsaspekt hätte ich nicht gedacht!
 
Einen Nachtrag noch: "is_readable" und danach "include" oder "require" ist natürlich NICHT atomar, das habe ich falsch dargestellt. is_readable gilt nur für den Zeitpunkt des Aufrufes, es kann also sein das zwischen is_readable und require ein Taktzyklus liegt, der die Datei löscht. Es ist also sinnvoller sich einen eigenen error-Handler zu machen und dann entsprechend damit zu arbeiten, wobei zu beachten ist, dass include() nur eine Warnung wirft und require() gleich einen Fatal Error.

sorry nochmal, war mein Fehler :-(
 
Ich denke dieser Fall wird wohl sehr selten auftreten...

Und wenn, dann ist wohl auch Pech.
Ich denke wenn jemand das entsprechende File löscht, ist das ein Ausrutscher oder so..

Und ansonsten ist das File hald ein Klick später vom User wirklich nicht mehr readable.. :)
 
Dieser Fehlerfall tritt gar nicht so selten ein und hat eine eigene Kategorie die sich "Race Conditions" ( http://www.php-faq.de/q/q-race-condition.html ) nennt, mal ist das mehr, mal weniger kritisch und ist meist gar nicht so schwer zu produzieren, und zwar einfach in dem man ne Menge gleichzeitiger Anfragen macht (ab aus dem Apache wäre so ein Tool, wenn auch nur sehr simpel).

Die Auswirkungen reichen vom "einfachen" Information Disclosure bis zu ernsthaften kritischen Lücken. Du fängst den Fehlerfall da auch nicht ab, das heißt, wenn es so kommt, befindet sich deine Anwendung in einem undefinierten Zustand und schmiert im besten Fall mit einer Fehlermeldung ab, die dann sogar wichtige Informationen enthalten kann (Pfade etc.).
 
Zurück