toscho.design

Zugriff verboten: Wie man Skripte gegen HTTP-Aufrufe sperrt

Manche Dateien möchten wir nur in andere einbinden: Konfigurationsdateien, Klassen oder Ähnliches. Sie sollen nie per HTTP aufgerufen werden, weil sie sensible Daten enthalten oder allein kein nützliches Ergebnis hervorbringen.
Dafür gibt es vier Wege.

Außerhalb des Wurzelverzeichnisses lagern

Einige Webhoster bieten einen FTP-Zugang an, bei dem wir oberhalb des Webverzeichnisses einsteigen. Sehr praktisch: Wir legen dort einfach ein Verzeichnis für die einzubindenden Dateien an und rufen sie dann ungefähr so auf:

require_once 
    dirname($_SERVER['DOCUMENT_ROOT']) 
    . DIRECTORY_SEPARATOR 
    . 'includes' 
    . DIRECTORY_SEPARATOR 
    . 'config.php';

Geschütztes Verzeichnis unterhalb der Wurzel

Wenn wir keinen Zugriff oberhalb des Wurzelverzeichnisses haben, dann legen wir eben eines darunter an und schützen es. Da bieten sich zwei Varianten an, die beide per .htaccess erzeugt werden.

Umleitung aus der generellen .htaccess:

Redirect permanent /includes/ http://localhost

Oder wir legen eine .htaccess in das geschützte Verzeichnis selbst und schreiben dort hinein:

Order allow,deny
Deny from all

Das Einbinden aus dem PHP-Skript sieht fast genauso aus:

require_once 
    $_SERVER['DOCUMENT_ROOT'] 
    . DIRECTORY_SEPARATOR 
    . 'includes' 
    . DIRECTORY_SEPARATOR 
    . 'config.php';

Bestimmte Endungen verbieten

Bei komplexeren Skripten möchten wir natürlich alle Dateien hübsch ordentlich in Verzeichnissen ablegen, deren Ordnung nicht vorrangig von der Zugriffskontrolle geprägt ist.

Hier benutze ich gerne die Endung inc für Includes. Angenehmer Nebeneffekt: Ich weiß schon beim Blick auf die Verzeichnisliste, welche Dateien wie aufgerufen werden sollen.

Vier Zeilen in der .htaccess verbieten den Zugriff auf alle Includes:

<Files *.inc>
    order allow,deny
    deny from all
</Files>

Kontrolle innerhalb der Datei

Das ist die scheußlichste Methode, weil man von außen nicht sieht, ob die Datei geschützt ist. Und leider ist es auch die häufigste.

Am Kopf der Datei steht eine … freiwillige Selbstkontrolle:

if ( 'geheim.php' == basename($_SERVER['SCRIPT_FILENAME']) )
{
	die('Bitte nicht direkt aufrufen!');
}

Immerhin funktioniert sie – wie die erste Methode – auch dann, wenn der Anwender keinen Zugriff auf die .htaccess hat.

Dateirechte anpassen

Filezilla: chmod 640Schließlich können wir noch per FTP oder SSH den entsprechenden Dateien die Leserechte für anonyme Nutzer entziehen. Das funktioniert immer, und wir sehen es bei der Auflistung der einzelnen Verzeichnisse.

Dank an Alexander Schestag für diesen Nachtrag.

Verwandte Artikel

7 Kommentare

  1. David am 10.01.2010 · 14:39

    Php-Dateien enden bei mir immer auf .php! Nicht auf .inc.php nicht auf .class.php oder änliche Späße und schon gar nicht auf .inc. Vergisst man mal die Sperre, dann wird der Code auf die Endung .inc nicht interpretiert sondern einfach an den Browser gesendet. Und das ist noch schlimmer als wenn er direkt aufgerufen und ausgeführt wird.

  2. Thomas Scholz am 10.01.2010 · 16:19

    @David: Auf den Gedanken, daß man seine Dateien zwar so benennen aber die Sperre vergessen könne, bin ich gar nicht gekommen. Ist mir noch nie passiert.
    Ich bevorzuge diese Methode ob der guten Übersicht, die sie mitbringt. Und wer das mag, wird den Eintrag in der .htaccess sicher nicht weglassen.

  3. David am 11.01.2010 · 11:14

    Übersichtlich ist das schon, das gebe ich zu. Allerdings schafft man das auch durch eine sinnvolle Ordnerstruktur.

  4. GMT am 11.01.2010 · 11:52

    Ich gehe da einen "Mittelweg". Bei mir fangen alle Dateinamen für Includes mit inc_ an und enden mit .php.

    Erfüllt seinen Zweck hinsichtlich Übersicht und der Code wird immer nur ausgeführt.

  5. Thomas Scholz am 12.01.2010 · 16:30

    @GMT: Ich möchte in meinen Skripten sicherstellen, daß keine Daten oder Codestücke sichtbar werden, wenn PHP ausfällt, während der Server noch läuft.
    Die Übersichtlichkeit sehe ich hierbei nur als angenehmen Nebeneffekt, deshalb empfinde ich deine Namenskonvention nicht unbedingt als Mittelweg.

  6. GMT am 12.01.2010 · 17:31

    Nun, das treibt den Sicherheitsgedanken auf die Spitze und geht noch einen Schritt weiter als nur das eingangs formulierte "Manche Dateien ...".

  7. mantiz am 12.01.2010 · 20:03

    Von den Inc-Dateien würde ich aus bereits genannten Gründen dringend abraten, besonders, wenn nicht direkt darauf hingewiesen wird, dass diese ggfs. nicht im PHP-Interpreter ausgeführt werden.

    In meinen Anfängen habe ich auch mit inc-files gearbeitet, bis es mir mal passiert ist, dass jmd. den Pfad zur Config-Datei durch eine Fehlermeldung leicht erraten konnte und somit sämtliche Infos hatte. :)

    Config- und Klassen-Dateien enthalten bei mir keinerlei (direkt) ausführbaren Code mehr, d.h. im schlimmsten Fall erscheint eine leere Seite. Zusätzlich schütze ich die entsprechenden Verzeichnisse sicherheitshalber per .htaccess. Der Schutz per .htaccess soll dazu dienen, falls der PHP-Interpreter mal ausfällt, die Endung .php deckt den Fall ab, dass der Eintrag in der .htaccess mal fehlen sollte.

    Es sollte beides nicht passieren, so kann man aber beidem etwas entgegenwirken und ein Problem hat man erst, wenn beides nicht greift.

    Ansonsten sollte man, falls möglich, die Dateien außerhalb der DocRoot speichern, was wohl die sicherste Variante darstellt.

    Bzgl. der Dateirechte muss ich anmerken, dass dies keine wirkliche Alternative darstellt. Ich habe es auf meinem Server gerade getestet, was dazu führte, dass die Datei nicht mehr von PHP eingelesen werden konnte. Ist auch klar, denn mein Apache läuft unter 'nobody:nogroup' und der FTP-User ist weder 'nobody', noch gehört er zu 'nogroup'. Da PHP als mod_php installiert ist, wird es unter dem Apache-User, also 'nobody' ausgeführt.
    Wenn PHP als CGI ausgeführt wird, mag das evtl. eine Option sein, aber so nicht.