wake-up-neo.com

Verhindern Sie direkten Zugriff auf eine PHP-Include-Datei

Ich habe eine PHP-Datei, die ich ausschließlich als Include verwenden werde. Deshalb möchte ich einen Fehler auslösen, anstatt ihn auszuführen, wenn auf ihn direkt zugegriffen wird, indem er die URL eingibt und nicht eingeschlossen wird.

Grundsätzlich muss ich die PHP-Datei folgendermaßen überprüfen:

if ( $REQUEST_URL == $URL_OF_CURRENT_PAGE ) die ("Direct access not premitted");

Gibt es einen einfachen Weg, dies zu tun?

148
Alterlife

Der einfachste Weg für die generische "PHP-App, die auf einem Apache-Server ausgeführt wird und möglicherweise nicht vollständig kontrolliert wird" besteht darin, die Include-Dateien in einem Verzeichnis abzulegen und den Zugriff auf dieses Verzeichnis in der .htaccess-Datei zu verweigern. Um den Leuten die Mühe des Googlens zu ersparen, wenn Sie Apache verwenden, fügen Sie dies in eine Datei mit dem Namen ".htaccess" in das Verzeichnis ein, auf das Sie nicht zugreifen können:

Deny from all

Wenn Sie tatsächlich die volle Kontrolle über den Server haben (heutzutage selbst für kleine Apps häufiger als beim ersten Schreiben dieser Antwort), sollten Sie die Dateien, die Sie schützen möchten, am besten außerhalb des Verzeichnisses ablegen, aus dem Ihr Webserver dient . Wenn sich Ihre App in /srv/YourApp/ befindet, stellen Sie den Server so ein, dass er Dateien von /srv/YourApp/app/ bereitstellt, und fügen Sie die Include-Dateien in /srv/YourApp/includes ein, sodass buchstäblich keine URL vorhanden ist, die auf sie zugreifen kann.

153
Chuck

Fügen Sie dies der Seite hinzu, die nur enthalten sein soll

<?php
if(!defined('MyConst')) {
   die('Direct access not permitted');
}
?>

dann auf den Seiten, die es enthalten, hinzufügen

<?php
define('MyConst', TRUE);
?>
169
UnkwnTech

Ich habe eine Datei, die ich anders behandeln muss, wenn sie enthalten ist, wenn sie direkt abgerufen wird (hauptsächlich print() vs return()).

if(count(get_included_files()) ==1) exit("Direct access not permitted.");

Die Datei, auf die zugegriffen wird, ist immer eine eingeschlossene Datei, daher das == 1.

104
null

Der beste Weg, den direkten Zugriff auf Dateien zu verhindern, besteht darin, sie außerhalb des Web-Server-Dokumentenstamms zu platzieren (normalerweise eine Ebene darüber). Sie können sie immer noch hinzufügen, aber es besteht keine Möglichkeit, dass jemand über eine http-Anfrage auf sie zugreift.

Normalerweise gehe ich den ganzen Weg und platziere alle meine PHP -Dateien außerhalb der Dokumentwurzel neben der bootstrap-Datei - einer einsamen index.php-Datei in der Dokumentwurzel, die die gesamte Website/Anwendung leitet .

31
Eran Galperin

Eine Alternative (oder Ergänzung) zu Chucks Lösung wäre, den Zugriff auf Dateien, die einem bestimmten Muster entsprechen, zu verweigern, indem Sie etwas in Ihre .htaccess-Datei einfügen

<FilesMatch "\.(inc)$">
    Order deny,allow
    Deny from all
</FilesMatch>
25
Kevin Loney

1: Überprüfen der Anzahl der enthaltenen Dateien

if( count(get_included_files()) == ((version_compare(PHP_VERSION, '5.0.0', '>='))?1:0) )
{
    exit('Restricted Access');
}

Logic: PHP wird beendet, wenn die minimale Anzahl der Einschlüsse nicht erreicht wird. Beachten Sie, dass die Basisseite vor PHP5 nicht als Include betrachtet wird.


2: Definieren und Überprüfen einer globalen Konstante

// In the base page (directly accessed):
define('_DEFVAR', 1);

// In the include files (where direct access isn't permitted):
defined('_DEFVAR') or exit('Restricted Access');

Logic: Wenn die Konstante nicht definiert ist, wurde die Ausführung nicht von der Basisseite aus gestartet, und PHP würde die Ausführung beenden.


3: Remote Adressautorisierung

// Call the include from the base page(directly accessed):
$includeData = file_get_contents("http://127.0.0.1/component.php?auth=token");

// In the include files (where direct access isn't permitted):
$src = $_SERVER['REMOTE_ADDR']; // Get the source address
$auth = authoriseIP($src); // Authorisation algorithm
if( !$auth ) exit('Restricted Access');

Der Nachteil dieser Methode ist die isolierte Ausführung, sofern nicht ein Session-Token mit der internen Anforderung bereitgestellt wird. Überprüfen Sie dies über die Loop-Back-Adresse im Falle einer einzelnen Serverkonfiguration oder einer Adressliste für eine Server- oder Serverinfrastruktur mit mehreren Servern.


4: Token-Autorisierung

Ähnlich wie bei der vorherigen Methode können Sie GET oder POST verwenden, um ein Berechtigungstoken an die Include-Datei zu übergeben:

if($key!="serv97602"){header("Location: ".$Dart);exit();}

Eine sehr unordentliche Methode, aber auch die sicherste und vielseitigste Methode, wenn sie richtig eingesetzt wird.


5: Webserver-spezifische Konfiguration

Bei den meisten Servern können Sie Berechtigungen für einzelne Dateien oder Verzeichnisse zuweisen. Sie können alle Ihre Include-Dateien in solchen eingeschränkten Verzeichnissen ablegen und den Server so konfigurieren, dass er sie ablehnt.

In Apache zum Beispiel wird die Konfiguration in der .htaccess-Datei gespeichert. Tutorial hier .

Beachten Sie jedoch, dass serverseitige Konfigurationen von mir nicht empfohlen werden, da sie für die Portabilität auf verschiedenen Webservern schlecht sind. In solchen Fällen, in denen der Deny-Algorithmus komplex ist oder die Liste der abgelehnten Verzeichnisse ziemlich groß ist , Es werden möglicherweise nur Rekonfigurationssitzungen eher grausam. Am Ende sollte dies am besten im Code behandelt werden.


6: Platzieren in einem sicheren Verzeichnis AUSSERHALB des Site-Root

Am wenigsten bevorzugt aufgrund von Zugriffsbeschränkungen in Serverumgebungen, aber eine recht leistungsfähige Methode, wenn Sie Zugriff auf das Dateisystem haben.

//Your secure dir path based on server file-system
$secure_dir=dirname($_SERVER['DOCUMENT_ROOT']).DIRECTORY_SEPARATOR."secure".DIRECTORY_SEPARATOR;
include($secure_dir."securepage.php");

Logik:

  • Der Benutzer kann keine Datei außerhalb des htdocs-Ordners anfordern, da die Links außerhalb des Adressensystems der Website liegen würden.
  • Der PHP-Server greift nativ auf das Dateisystem zu und kann somit auf Dateien auf einem Computer zugreifen, genau wie ein normales Programm mit den erforderlichen Berechtigungen.
  • Indem Sie die Include-Dateien in diesem Verzeichnis ablegen, können Sie sicherstellen, dass der PHP-Server auf sie zugreifen kann, während dem Benutzer Hotlinks verweigert werden.
  • Selbst wenn die Konfiguration des Dateisystems des Webservers nicht ordnungsgemäß durchgeführt wurde, verhindert diese Methode, dass diese Dateien versehentlich öffentlich werden.

Bitte entschuldigen Sie meine unorthodoxen Kodierungskonventionen. Jedes Feedback wird geschätzt.

22
RiA

Eigentlich ist mein Rat, all diese Best Practices anzuwenden.

  • Legen Sie die Dokumente außerhalb des Webroots OR in einem Verzeichnis ab, dem der Webserver AND den Zugriff verweigert
  • Verwenden Sie in Ihren sichtbaren Dokumenten eine Definition, nach der die verborgenen Dokumente suchen:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

Wenn die Dateien auf irgendeine Weise falsch platziert werden (eine fehlerhafte FTP-Operation), sind sie auf diese Weise weiterhin geschützt.

14
jmucchiello

Ich hatte dieses Problem einmal gelöst mit:

if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...

die ideale Lösung besteht jedoch darin, die Datei außerhalb des Web-Server-Dokumentenstamms zu platzieren, wie in einem anderen Server erwähnt.

7
mati

Sie sollten eine Anwendung mit einem Einstiegspunkt erstellen, d. H. Alle Dateien sollten über index.php erreicht werden

Platzieren Sie dies in index.php

define(A,true);

Diese Prüfung sollte in jeder verknüpften Datei ausgeführt werden (via Require oder Include).

defined('A') or die(header('HTTP/1.0 403 Forbidden'));
5
user2221806
debug_backtrace() || die ("Direct access not permitted");
4
Unirgy

Ich wollte den Zugriff auf die DateiPHPdirekt einschränken, aber auch über jQuery $.ajax (XMLHttpRequest) aufrufen können. Hier ist was für mich gearbeitet hat.

if (empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] != "XMLHttpRequest") {
    if (realpath($_SERVER["SCRIPT_FILENAME"]) == __FILE__) { // direct access denied
        header("Location: /403");
        exit;
    }
}
4
krasenslavov

Was für ein Joomla! Dabei wird eine Konstante in einer Root-Datei definiert und geprüft, ob diese in den enthaltenen Dateien definiert ist.

defined('_JEXEC') or die('Restricted access');

oder aber 

man kann alle Dateien außerhalb der Reichweite einer http-Anfrage halten, indem man sie außerhalb des Webroot-Verzeichnisses ablegt, wie es die meisten Frameworks wie CodeIgniter empfehlen. 

sie können sogar den Direktzugriff verhindern, indem Sie eine .htaccess-Datei innerhalb des Include-Ordners platzieren und Regeln schreiben.

4
Pradeesh kumar

Am einfachsten ist es, eine Variable in der Datei festzulegen, die Aufrufe enthalten, wie z

$including = true;

Suchen Sie dann in der Datei, die aufgenommen wird, nach der Variablen

if (!$including) exit("direct access not permitted");
4
Kyle Cronin

Neben dem .htaccess-Weg habe ich ein nützliches Muster in verschiedenen Frameworks gesehen, beispielsweise in Ruby on Rails. Sie haben ein separates pub/-Verzeichnis im Stammverzeichnis der Anwendung, und die Bibliotheksverzeichnisse befinden sich in Verzeichnissen im Verzeichnis das selbe Level als Kneipe /. So etwas (nicht ideal, aber man bekommt die Idee):

app/
 |
 +--pub/
 |
 +--lib/
 |
 +--conf/
 |
 +--models/
 |
 +--views/
 |
 +--controllers/

Sie haben Ihren Webserver so eingerichtet, dass pub/als Dokumentstammverzeichnis verwendet wird. Dies bietet einen besseren Schutz für Ihre Skripts: Sie können zwar über die Dokumentwurzel erreichen, um die erforderlichen Komponenten zu laden, aber es ist unmöglich, auf die Komponenten über das Internet zuzugreifen. Ein weiterer Vorteil neben der Sicherheit ist, dass alles an einem Ort ist.

Dieses Setup ist besser als das Erstellen von Überprüfungen in jeder einzelnen eingeschlossenen Datei, da die Meldung "Zugriff nicht zulässig" ein Hinweis für Angreifer ist und die Konfiguration besser als .htaccess ist, da sie nicht auf einer Whitelist basiert: wenn Sie die Dateierweiterungen vermasseln In den Verzeichnissen lib /, conf/usw. ist sie nicht sichtbar.

3
bandi

Wenn genauer, sollten Sie diese Bedingung verwenden:

if (array_search(__FILE__, get_included_files()) === 0) {
    echo 'direct access';
}
else {
    echo 'included';
}

get_included_files () gibt ein indiziertes Array zurück, das die Namen aller eingeschlossenen Dateien enthält (wenn die Datei beign ausgeführt wird, wurde sie eingeschlossen und der Name befindet sich im Array) ..__ Wenn also direkt auf die Datei zugegriffen wird, ist ihr Name Bei der ersten im Array wurden alle anderen Dateien im Array eingeschlossen.

2
Oleg Lokshyn
if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };
1
andy
<?php
if (eregi("YOUR_INCLUDED_PHP_FILE_NAME", $_SERVER['PHP_SELF'])) { 
 die("<h4>You don't have right permission to access this file directly.</h4>");
}
?>

platzieren Sie den Code oben in der enthaltenen PHP-Datei.

ex:

<?php
if (eregi("some_functions.php", $_SERVER['PHP_SELF'])) {
    die("<h4>You don't have right permission to access this file directly.</h4>");
}

    // do something
?>
1
Blogging Tips

Der folgende Code wird im Flatnux-CMS ( http://flatnux.altervista.org ) verwendet:

if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
    header("Location: ../../index.php");
    die("...");
}
1
JohnRDOrazio

Meine Antwort ist etwas anders, enthält aber viele der hier gegebenen Antworten. Ich würde einen mehrstufigen Ansatz empfehlen:

  1. .htaccess und Apache Einschränkungen sicher
  2. defined('_SOMECONSTANT') or die('Hackers! Be gone!');

JEDOCH Der Ansatz defined or die weist eine Reihe von Fehlern auf. Erstens ist es ein echtes Problem, die Annahmen zu testen und mit denen zu debuggen. Zweitens geht es um entsetzliches, irrsinnig langweiliges Refactoring, wenn Sie Ihre Meinung ändern. "Suchen und Ersetzen!" du sagst. Ja, aber wie sicher bist du dir, dass es überall genauso geschrieben ist, hmmm? Jetzt multipliziere das mit Tausenden von Dateien ... o.O.

Und dann ist da noch .htaccess. Was passiert, wenn Ihr Code auf Websites verteilt wird, auf denen der Administrator nicht so gewissenhaft ist? Wenn Sie sich nur auf .htaccess verlassen, um Ihre Dateien zu sichern, benötigen Sie außerdem a) eine Sicherungskopie, b) eine Schachtel Taschentücher, um Ihre Tränen zu trocknen, c) einen Feuerlöscher, um die Flammen aller Hatemails von Menschen zu löschen Verwenden Sie Ihren Code.

Ich weiß, dass die Frage nach der "einfachsten" fragt, aber ich denke, dies erfordert mehr "defensive Codierung".

Was ich vorschlage ist:

  1. Vor einem Ihrer Skripte require('ifyoulieyougonnadie.php'); (notinclude() und als Ersatz für defined or die)
  2. Führen Sie in ifyoulieyougonnadie.php Einige logische Aufgaben aus - suchen Sie nach verschiedenen Konstanten, rufen Sie ein Skript auf, testen Sie localhost usw. - und implementieren Sie dann Ihre die(), throw new Exception, 403 usw.

    Ich erstelle mein eigenes Framework mit zwei möglichen Einstiegspunkten - dem Hauptindex.php (Joomla-Framework) und dem Ajaxrouter.php (meinem Framework) - also überprüfe ich je nach Einstiegspunkt, ob es verschiedene Dinge gibt. Wenn die Anfrage nach ifyoulieyougonnadie.php Nicht aus einer dieser beiden Dateien kommt, weiß ich, dass Shenanigans unternommen werden!

    Aber was ist, wenn ich einen neuen Einstiegspunkt hinzufüge? Keine Bange. Ich ändere nur ifyoulieyougonnadie.php Und bin sortiert, plus kein "Suchen und Ersetzen". Hurra!

    Was ist, wenn ich mich entschlossen habe, einige meiner Skripte zu verschieben, um ein anderes Framework zu erstellen, das nicht die gleichen Konstanten defined() hat? ... Hurra! ^ _ ^

Ich fand, dass diese Strategie die Entwicklung viel spaßiger und viel weniger macht:

/**
 * Hmmm... why is my netbeans debugger only showing a blank white page 
 * for this script (that is being tested outside the framework)?
 * Later... I just don't understand why my code is not working...
 * Much later... There are no error messages or anything! 
 * Why is it not working!?!
 * I HATE PHP!!!
 * 
 * Scroll back to the top of my 100s of lines of code...
 * U_U
 *
 * Sorry PHP. I didn't mean what I said. I was just upset.
 */

 // defined('_JEXEC') or die();

 class perfectlyWorkingCode {}

 perfectlyWorkingCode::nowDoingStuffBecauseIRememberedToCommentOutTheDie();
1
Just Plain High
if ( ! defined('BASEPATH')) exit('No direct script access allowed');

wird die Arbeit reibungslos erledigen

0
Varshaan

Sie können phpMyAdmin Style verwenden: 

/**
 * block attempts to directly run this script
 */
if (getcwd() == dirname(__FILE__)) {
    die('Attack stopped');
}
0
namco
<?php       
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
  if (false !== strpos($url,'.php')) {
      die ("Direct access not premitted");
  }
?>
0
Matt Bettiol

dies ist, was Google in ihren PHP-Beispielen verwendet siehe hier

if (php_sapi_name() != 'cli') {
  throw new \Exception('This application must be run on the command line.');
}
0
Toskan

Das Speichern Ihrer Include-Dateien außerhalb des über das Internet zugänglichen Verzeichnisses wurde bereits einige Male erwähnt und ist sicherlich eine gute Strategie, wenn dies möglich ist. Eine weitere Option, die ich noch nicht gesehen habe, ist: Stellen Sie sicher, dass Ihre Include-Dateien keinen ausführbaren Code enthalten . Wenn Ihre Include-Dateien lediglich Funktionen und Klassen definieren und keinen anderen Code aufweisen, wird beim direkten Zugriff einfach eine leere Seite erstellt.

Erlauben Sie auf jeden Fall den direkten Zugriff auf diese Datei über den Browser: wird nichts tun . Es definiert einige Funktionen, von denen jedoch keine aufgerufen wird, sodass keine ausgeführt wird.

<?php

function a() {
    // function body
}

function b() {
    // function body
}

Gleiches gilt für Dateien, die nur PHP Klassen enthalten, und sonst nichts.


Es ist immer noch eine gute Idee, Ihre Dateien möglichst außerhalb des Webverzeichnisses zu speichern.

  • Sie können aus Versehen PHP deaktivieren. In diesem Fall sendet Ihr Server möglicherweise den Inhalt der PHP -Dateien an den Browser, anstatt PHP auszuführen und das Ergebnis zu senden. Dies kann dazu führen, dass Ihr Code (einschließlich Datenbankkennwörtern, API-Schlüsseln usw.) undicht wird.
  • Dateien im Webverzeichnis hocken auf URLs, die Sie möglicherweise für Ihre App verwenden möchten. Ich arbeite mit einem CMS, das keine Seite mit dem Namen system haben kann, da dies zu einem Konflikt mit einem für den Code verwendeten Pfad führen würde. Das finde ich nervig.
0
TRiG

Was Sie auch tun können, ist das Verzeichnis mit einem Kennwort zu schützen und alle Ihre PHP-Skripts dort zu behalten, natürlich mit Ausnahme der Datei index.php, da zum Zeitpunkt von include kein Kennwort erforderlich ist, da es nur für den HTTP-Zugriff erforderlich ist. Sie erhalten außerdem die Möglichkeit, auf Ihre Skripts zuzugreifen, falls Sie dies wünschen, da Sie über ein Kennwort verfügen, um auf dieses Verzeichnis zuzugreifen. Sie müssen die .htaccess-Datei für das Verzeichnis und eine .htpasswd-Datei einrichten, um den Benutzer zu authentifizieren.

nun, Sie können auch eine der oben genannten Lösungen verwenden, wenn Sie der Meinung sind, dass Sie normalerweise nicht auf diese Dateien zugreifen müssen, da Sie immer über cPanel usw. darauf zugreifen können.

Hoffe das hilft

0
RohitG

Tun Sie etwas wie:

<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
    header('HTTP/1.0 403 Forbidden');
    exit('Forbidden');
}
?>
0
kmkaplan

Ich fand die Vorschläge mit .htaccess nicht so gut, weil sie Anderen Inhalt in diesem Ordner blockieren könnten, auf den der Benutzer möglicherweise zugreifen möchte. Dies ist meine Lösung:

$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if($currentFileInfo['basename'] == $requestInfo['basename']){
    // direct access to file
}
0
talsibony

ich schlage vor, $_SERVER aus Sicherheitsgründen nicht zu verwenden.
Sie können eine Variable wie $root=true; in der ersten Datei verwenden, die eine andere enthält.
und verwenden Sie isset($root) am Anfang der zweiten Datei, die aufgenommen werden soll. 

0
Mohamad Rostami

Sie können die folgende Methode verwenden, obwohl sie einen Fehler aufweist, da sie gefälscht werden kann, es sei denn, Sie können eine weitere Codezeile hinzufügen, um sicherzustellen, dass die Anforderung nur von Ihrem Server stammt, entweder mit Javascript ..__ Platzieren Sie diesen Code im Body-Abschnitt Ihres HTML-Codes, damit der Fehler dort angezeigt wird.

<?
if(!isset($_SERVER['HTTP_REQUEST'])) { include ('error_file.php'); }
else { ?>

Fügen Sie hier Ihren anderen HTML-Code ein

<? } ?>

Beenden Sie es so, also wird die Ausgabe des Fehlers immer im Hauptteil angezeigt, wenn Sie es so wollen.

0
Charming Prince

Ich habe diese php-only und unveränderliche Lösung gefunden, die sowohl mit http als auch mit cli funktioniert: 

Eine Funktion definieren: 

function forbidDirectAccess($file) {
    $self = getcwd()."/".trim($_SERVER["PHP_SELF"], "/");
    (substr_compare($file, $self, -strlen($self)) != 0) or die('Restricted access');
}

Rufen Sie die Funktion in der Datei auf, zu der der direkte Zugriff verhindert werden soll: 

forbidDirectAccess(__FILE__);

Die meisten der oben genannten Lösungen für diese Frage funktionieren nicht im Cli-Modus.

0
Ka.

Die einfachste Möglichkeit besteht darin, Ihre Include-Dateien außerhalb des Webverzeichnisses zu speichern. Auf diese Weise hat der Server Zugriff auf sie, aber keine externen Maschinen. Der einzige Nachteil ist, dass Sie auf diesen Teil Ihres Servers zugreifen können. Der Vorteil ist, dass keine Einrichtung, Konfiguration oder zusätzlicher Code/Server-Stress erforderlich ist.

0
user1391838