Предотвратите прямой доступ к файлу включения php

У меня есть php файл, который я буду использовать исключительно как include. Поэтому я хотел бы сделать ошибку, а не выполнять ее, когда она обратилась непосредственно, введя URL вместо того, чтобы быть включенным.

В основном мне нужно сделать проверку в файле php следующим образом:

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

Есть ли простой способ сделать это?

Ответ 1

Самый простой способ для общего "PHP-приложения, работающего на сервере Apache, который вы можете или не можете полностью контролировать", - это включить ваши включения в каталог и запретить доступ к этому каталогу в вашем файле .htaccess. Чтобы спасти людей от проблемы с Google, если вы используете Apache, поместите это в файл с именем ".htaccess" в каталог, который вы не хотите быть доступным:

Deny from all

Если у вас действительно есть полный контроль над сервером (более распространенный в наши дни даже для небольших приложений, чем когда я впервые написал этот ответ), лучший подход заключается в том, чтобы хранить файлы, которые вы хотите защитить, за пределами каталога, который ваш веб-сервер обслуживает. Поэтому, если ваше приложение находится в /srv/YourApp/, установите сервер для работы с файлами из /srv/YourApp/app/ и поместите его в /srv/YourApp/includes, поэтому там не будет никакого URL-адреса, который может получить к ним доступ.

Ответ 2

Добавьте это на страницу, которую вы хотите включить только

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

затем на страницах, которые включают его, добавьте

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

Ответ 3

У меня есть файл, который мне нужно действовать по-разному, когда он включал vs, когда он обращался напрямую (в основном print() vs return()). Здесь был изменен код:

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

Доступ к файлу всегда является включенным файлом, поэтому == 1.  

Ответ 4

Лучший способ предотвратить прямой доступ к файлам - разместить их вне корня документа веб-сервера (обычно на одном уровне выше). Вы все еще можете включить их, но нет возможности доступа к ним через HTTP-запрос.

Обычно я прохожу весь путь и размещаю все мои PHP файлы за пределами корня документа в стороне от загрузочного файла - одиночный индекс .php в корневом каталоге документа, который начинает маршрутизацию всего веб-сайта/приложения.

Ответ 5

Альтернативой (или дополнением) к решению Chuck было бы запретить доступ к файлам, соответствующим определенному шаблону, помещая что-то подобное в ваш .htaccess файл

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

Ответ 6

1: Проверка количества включенных файлов

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

Логика: PHP завершается, если минимальное число включений не выполнено. Обратите внимание, что до PHP5 базовая страница не считается включаемой.


2: определение и проверка глобальной константы

// 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');

Логика: если константа не определена, то выполнение не начнется с базовой страницы, и PHP прекратит выполнение.


3: Удаленная авторизация адреса

// 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');

Недостатком этого метода является изолированное выполнение, если только токен сеанса не предоставлен с внутренним запросом. Проверьте через адрес обратной связи в случае конфигурации с одним сервером или белый список адресов для многосерверной или серверной инфраструктуры с балансировкой нагрузки.


4: авторизация токена

Как и в предыдущем методе, можно использовать GET или POST для передачи токена авторизации во включаемый файл:

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

Очень грязный метод, но, пожалуй, самый безопасный и универсальный одновременно, при правильном использовании.


5: Конфигурация веб-сервера

Большинство серверов позволяют вам назначать разрешения для отдельных файлов или каталогов. Вы можете поместить все ваши включения в такие ограниченные каталоги и настроить сервер на их запрет.

Например, в APACHE конфигурация хранится в файле .htaccess. Учебник здесь.

Однако обратите внимание, что специфичные для сервера конфигурации не рекомендуются мной, потому что они плохо подходят для переносимости между различными веб-серверами. В тех случаях, когда алгоритм deny сложен или список запрещенных каталогов довольно велик, он может сделать сеансы реконфигурации только ужасными. В конце концов, лучше всего обработать это в коде.


6: Размещение включает в безопасном каталоге за пределами корня сайта

Наименее предпочтительный из-за ограничений доступа в серверных средах, но довольно мощный метод, если у вас есть доступ к файловой системе.

//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");

Логика:

  • Пользователь не может запросить какой-либо файл за пределами папки htdocs поскольку ссылки будут выходить за рамки адресной системы сайта.
  • Php-сервер напрямую обращается к файловой системе и, следовательно, может обращаться к файлам на компьютере так же, как это делает обычная программа с необходимыми привилегиями.
  • Размещая включаемые файлы в этом каталоге, вы можете гарантировать, что php-сервер получит к ним доступ, в то время как горячая ссылка запрещена для пользователя.
  • Даже если настройка доступа к файловой системе веб-сервера не была выполнена должным образом, этот метод предотвратит случайное обнародование этих файлов.

Пожалуйста, извините за мои неортодоксальные соглашения о кодировании. Любые отзывы приветствуются.

Ответ 7

Вообще-то мой совет - сделать все эти лучшие практики.

  • Поместите документы за пределы webroot ИЛИ в каталог, которому запрещен доступ к веб-серверу И
  • Используйте в своих видимых документах определение, которое скрытые документы проверяют:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

Таким образом, если файлы каким-то образом утеряны (операция errant ftp), они все еще защищены.

Ответ 8

У меня была эта проблема, решена с помощью:

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

но идеальным решением является размещение файла за пределами корня документа веб-сервера, как указано в другом андресе.

Ответ 9

Лучше создать приложение с одной точкой входа, т.е. все файлы должны быть получены из index.php

Поместите это в index.php

define(A,true);

Эта проверка должна выполняться в каждом связанном файле (через require или include)

defined('A') or die(header('HTTP/1.0 403 Forbidden'));

Ответ 10

Самый простой способ - установить некоторую переменную в файл, который включает include, например

$including = true;

Затем в включенном файле проверьте переменную

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

Ответ 11

Что такое Joomla! is определяет константу в корневом файле и проверяет, совпадает ли ее с включенными файлами.

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

или еще

можно хранить все файлы вне досягаемости HTTP-запроса, помещая их вне каталога webroot, поскольку большинство фреймворков, таких как CodeIgniter, рекомендуют.

или даже путем размещения файла .htaccess внутри папки include и написания правил, вы можете предотвратить прямой доступ.

Ответ 12

debug_backtrace() || die ("Direct access not permitted");

Ответ 13

Помимо пути .htaccess, я видел полезный шаблон в различных рамках, например, в ruby ​​on rails. У них есть отдельный каталог pub/в корневом каталоге приложения, а каталоги библиотек живут в каталогах на уровне того же уровня, что и pub/. Что-то вроде этого (не идеально, но вы получаете идею):

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

Вы настроили свой веб-сервер для использования pub/as root. Это обеспечивает лучшую защиту ваших скриптов: в то время как они могут протянуться из корня документа для загрузки необходимых компонентов, невозможно получить доступ к компонентам из Интернета. Еще одно преимущество, помимо безопасности, заключается в том, что все находится в одном месте.

Эта настройка лучше, чем просто создание проверок в каждом отдельном файле, потому что сообщение "доступ не разрешено" является подсказкой для злоумышленников, и это лучше, чем настройка .htaccess, потому что это не белый список: если вы испортите расширения файлов он не будет отображаться в каталогах lib/, conf/etc.

Ответ 14

Я хотел напрямую ограничить доступ к файлу PHP, но также иметь возможность называть его через jQuery $.ajax (XMLHttpRequest). Вот что сработало для меня.

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;
    }
}

Ответ 15

Если точнее, вы должны использовать это условие:

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

get_included_files() возвращает индексированный массив, содержащий имена всех включенных файлов (если файл beign выполнен, то он был включен и его имя находится в массив). Таким образом, когда файл имеет прямой доступ, его имя является первым в массиве, все остальные файлы в массиве были включены.

Ответ 16

<?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>");
}
?>

поместите код выше в верхней части вашего включенного php файла.

Пример:

<?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
?>

Ответ 17

Следующий код используется в CMS Flatnux (http://flatnux.altervista.org):

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

Ответ 18

if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };

Ответ 19

Мой ответ несколько иной в подходе, но включает в себя многие ответы, представленные здесь. Я бы рекомендовал многопростовый подход:

  • .htaccess и ограничения Apache.
  • defined('_SOMECONSTANT') or die('Hackers! Be gone!');

ОДНАКО Подход defined or die имеет ряд недостатков. Во-первых, это настоящая боль в предположениях для тестирования и отладки. Во-вторых, это связано с ужасающим, умопомрачительно скучным рефакторингом, если вы передумаете. "Найти и заменить!" ты говоришь. Да, но насколько ты уверен, что все написано точно так же везде, хммм? Теперь умножьте это на тысячи файлов... o.O

И тогда там .htaccess. Что произойдет, если ваш код будет распространен на сайтах, где администратор не так скрупулезен? Если вы полагаетесь только на .htaccess для защиты ваших файлов, вам также понадобится: a) резервная копия, b) ящик тканей для высыхания ваших слез, c) огнетушитель, чтобы погасить огонь во всей ленте от людей используя ваш код.

Итак, я знаю, что вопрос требует "самого легкого", но я думаю, что это требует более "защитного кодирования".

Я предлагаю:

  • Перед любыми вашими сценариями require('ifyoulieyougonnadie.php'); ( не include() и в качестве замены для defined or die)
  • В ifyoulieyougonnadie.php выполните некоторые логические операции - проверьте разные константы, вызовите script, тестирование localhost и т.д., а затем выполните свои die(), throw new Exception, 403 и т.д.

    Я создаю свою собственную фреймворк с двумя возможными точками входа - основной index.php(структура Joomla) и ajaxrouter.php(моя фреймворк) - поэтому в зависимости от точки входа я проверяю разные вещи. Если запрос на ifyoulieyougonnadie.php не поступает из одного из этих двух файлов, я знаю, что принимаются махинации!

    Но что, если я добавлю новую точку входа? Не беспокойся. Я просто изменяю ifyoulieyougonnadie.php, и меня сортируют, плюс нет "найти и заменить". Ура!

    Что делать, если я решил перенести некоторые мои скрипты, чтобы создать другую структуру, которая не имеет одинаковых констант defined()?... Ура! ^ _ ^

Я нашел, что эта стратегия делает разработку намного веселее и намного меньше:

/**
 * 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();

Ответ 20

Сделайте что-то вроде:

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

Ответ 21

Я нашел это php-only и неизменяемое решение, которое работает как с http, так и с cli:

Определите функцию:

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

Вызвать функцию в файле, для которого вы хотите запретить прямой доступ:

forbidDirectAccess(__FILE__);

Большинство решений, приведенных выше для этого вопроса, не работают в режиме Cli.

Ответ 22

Вы можете использовать следующий ниже метод, хотя он имеет недостаток, потому что его можно подделать, за исключением случаев, когда вы можете добавить еще одну строку кода, чтобы убедиться, что запрос поступает только с вашего сервера либо с помощью Javascript. Вы можете поместить этот код в раздел "Тело" вашего HTML-кода, поэтому там отображается ошибка.

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

Разместите свой другой HTML-код здесь

<? } ?>

Завершите это так, поэтому вывод ошибки всегда будет отображаться внутри секции тела, если это так, как вы хотите.

Ответ 23

Я предлагаю не использовать $_SERVER по соображениям безопасности.
Вы можете использовать переменную типа $root=true; в первом файле, которая включала другую.
и используйте isset($root) в начале второго файла, который будет включен.

Ответ 24

То, что вы также можете сделать, это защитить паролем директорию и сохранить там все ваши php-скрипты, конечно, за исключением файла index.php, так как на момент включения пароля не требуется, поскольку это потребуется только для http доступ. то, что он будет делать, также предоставляет вам возможность доступа к вашим скриптам в случае, если вы этого хотите, поскольку у вас будет пароль для доступа к этому каталогу. вам нужно будет установить файл .htaccess для каталога и файл .htpasswd для аутентификации пользователя.

хорошо, вы также можете использовать любое из вышеперечисленных решений, если вы считаете, что вам не нужно обращаться к этим файлам, потому что вы всегда можете получить к ним доступ через cPanel и т.д.

Надеюсь, что это поможет

Ответ 25

Самый простой способ - хранить ваши объекты за пределами веб-каталога. Таким образом, у сервера есть доступ к ним, но нет внешней машины. Единственная нижняя сторона - вам нужно иметь доступ к этой части вашего сервера. Поверхность - это не требует настройки, конфигурации или дополнительного стресса кода/сервера.

Ответ 26

<?php       
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
  if (false !== strpos($url,'.php')) {
      die ("Direct access not premitted");
  }
?>

Ответ 27

Я не нашел предложений с .htaccess настолько хорошо, что он может блокировать другой контент в этой папке, к которому вы, возможно, захотите разрешить пользователю доступ, это мое решение:

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

Ответ 28

if ( ! defined('BASEPATH')) exit('No direct script access allowed');

сделает работу гладкой

Ответ 29

Вы можете использовать стиль phpMyAdmin:

/**
 * block attempts to directly run this script
 */
if (getcwd() == dirname(__FILE__)) {
    die('Attack stopped');
}

Ответ 30

это то, что Google использует в своих примерах php см. здесь

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