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

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

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

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

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

вместо die () вы должны проверить заголовок '(«HTTP / 1.1 404 File Not Found», 404); выход;'. Это (по крайней мере, на apache) заставит сервер вернуть обычную страницу 404.

gnud 04.01.2009 20:08

Вот два простых метода, которые я объяснил, чтобы отключить прямой доступ к файлам, включенным в PHP: codepeedy.com/disable-direct-access-to-the-php-include-file

Faruque Ahamed Mollick 19.07.2017 00:06
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
174
2
234 974
33
Перейти к ответу Данный вопрос помечен как решенный

Ответы 33

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

$including = true;

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

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

Это опасно, если включен register_globals.

jmucchiello 03.01.2009 21:51
PHP опасен, если register_globals включен.
David Precious 03.01.2009 21:56

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

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

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

Beau Simensen 03.01.2009 22:29

В каждом хостинг-провайдере, с которым я работал, у меня всегда был доступ (ровно) на один уровень выше корня документа.

Eran Galperin 04.01.2009 00:21

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

Dinah 23.06.2009 19:43

Это также хорошая альтернатива ... используя preg_match -> if (preg_match ("~ globalfile \ .php ~ i", $ _SERVER ['PHP_SELF'])) {die ('<h3 style = "color: red"> Предупреждение системы безопасности устройства - прямой доступ запрещен! Ваш IP-адрес зарегистрирован! <h3> '); // Остановить дальнейшее выполнение}

MarcoZen 30.11.2017 18:13

Этот URL-адрес devzone.zend.com/node/view/id/70 теперь является 404-м. Ответ должен включать код, который изначально использовался с несуществующего URL.

Funk Forty Niner 08.05.2018 16:22
Ответ принят как подходящий

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

Deny from all

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

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

Alterlife 03.01.2009 21:23

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

Eineki 03.01.2009 22:43

Было бы неплохо включить в этот ответ пример файла .htaccess.

Graham Lea 05.06.2012 15:47
<Files ~ "\.inc$">Order Allow,DenyDeny from All</Files>
Dracorat 27.09.2012 20:53

Что делать, если вы используете nginx? :П

Matt 07.09.2013 03:09

@James: Кроме того, не все считают, что Stack Overflow должен быть сайтом «пожалуйста, отправьте код». Если он четко отвечает на вопрос, то это хороший ответ. Предоставление примера, когда ничего не требуется, только поощряет кодирование с копированием и вставкой.

Chuck 11.09.2013 01:03

@ Чак: Интересный ответ. За исключением того, что PHP - это язык масс. StackOverflow - это популярный сайт, посвященный PHP (конечно, кроме php.net). Большинство масс имеют несколько, э-э, «неясное» понимание безопасности веб-сайтов из-за того, что они не являются злыми хакерами. И настройка .htaccess ПРАВИЛЬНО на самом деле очень сложна. Я, например, не буду думать о вас меньше за помощь и подстрекательство к программированию C&P ... только в этот раз o.O. PS: Поместите туда кое-что кеширующее, потому что эти новички ничего не знают! Это стыдно. Настоящие кодеры (вроде нас) знают родившийся! :П

Just Plain High 06.12.2013 14:21

И чтобы объяснить мой отрицательный голос :( PHP-кодеры (особенно) должны стать намного более внимательными к безопасности сайта И безопасности кода. Это не одно и то же. Мы не должны поощрять решения единой стратегии - по крайней мере, не без упоминания подводных камней ( мой ответ ниже).

Just Plain High 06.12.2013 14:55

@HighPriestessofTheTech: Никаких обид. Вы должны голосовать против ответов, которые, по вашему мнению, не являются достаточно хорошей работой. Чтобы объяснить мою точку зрения: я не чувствую, что могу заставить плохих кодеров (не новичков, а плохих кодировщиков) писать хороший код. Я просто делаю все возможное, чтобы помогать людям, которые хотят попробовать и учиться. Что касается нескольких стратегий, мне не нравится делать одно и то же несколько раз. В большинстве случаев для меня это попахивает программированием вуду: «Я не уверен, что делаю это правильно, поэтому я сделаю две, возможно, неправильные вещи, и, надеюсь, одно сработает!» Но я все еще думаю, что ваш ответ хорош, так что +1 к вам.

Chuck 06.12.2013 22:49

При просмотре 55200+, я считаю, что именно здесь Google берет всех ^ _ ^ так что за правку +1 от меня - награда "убить двух зайцев одним выстрелом";) Спасибо за комплимент :) А теперь, если вы ' Простите, вернемся к вуду!

Just Plain High 07.12.2013 07:54

@Chuck Я попытался поместить следующий код в свой файл httpd.conf (я использую CentOS, и моя веб-страница сейчас полностью недоступна. Я пытаюсь выяснить, в чем проблема. <Directory "/ var / www / html / include "> AllowOverride All Allow from all </Directory> / var / www / html / include <= это был путь, который я хотел ограничить, чтобы люди не могли заходить в мои файлы через URL-адрес, обращаясь к примеру. com / include Как я могу выяснить, что я сделал не так? Я также попытался удалить строки, но моя веб-страница по-прежнему недоступна по URL-адресу

Mike_Moto 12.06.2014 00:13

Это действительно правильный ответ? Мне понадобится AllowOverride All в конфигурациях Apache, и это далеко не по умолчанию ни в одной из основных настроек ОС.

Sliq 21.10.2014 19:42

Я пробовал это, и если вы сделаете Deny from all, он даже не будет работать во включении, он будет 404.

Michael Rogers 03.07.2017 12:53

Я пробовал deny from all, но он также не дает мне сделать запрос на выборку из этих файлов, так что вы предлагаете мне сделать

Curtis Crentsil 08.08.2020 03:41

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

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

затем на страницах, содержащих его, добавьте

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

Мне действительно нужно научиться печатать быстрее. Я бы предложил тот же способ, поскольку он более безопасен, чем метод, использующий переменную для проверки. Поскольку с некоторыми настройками PHP можно переопределить переменную.

Mark Davidson 03.01.2009 21:17

Вот как с этим справляются некоторые «основные» приложения. Я знаю, что Joomla делает это таким образом, и я думаю, что Wiki, Wordpress и другие тоже.

UnkwnTech 03.01.2009 21:20

Возможно, сообщение слишком полезно для хакера (настоящий пользователь не найдет эти страницы), вы можете просто отправить заголовок перенаправления и остановить обработку php.

bandi 04.01.2009 13:05

Просто отправьте заголовок 404 и выйдите - страница с ошибкой будет выглядеть так же, как обычные страницы 404 (по крайней мере, на Apache).

gnud 04.01.2009 16:24

Если кто-то знает ваш код и создает страницу с вашими секретными константами, чтобы включить их? это обход вашей защиты?

Smile.Hunter 29.04.2013 22:21

@ Smile.Hunter: речь идет о блокировании доступа к просмотру ваших файлов сценариев include / library напрямую, ответ работает. Если они создали somefile.php на вашем сервере и добавили в него ваше определение, это по-прежнему не позволяет им напрямую обращаться к включаемому файлу. Это позволит им "включать" ваши файлы библиотеки, но если они зайдут достаточно далеко, чтобы создавать файлы на вашем сервере и знать ваши сценарии определения / включения, у вас есть другие проблемы, которые, вероятно, сводят на нет запись их собственного файла с вашим определением в первую очередь .

James 10.09.2013 20:43

Более короткий способ запретить доступ с тем же результатом: defined('MyConst') || die('Direct access not permitted');

MDeuerlein 10.01.2016 05:43

Хорошее решение, понравилось. Спасибо

krupesh Anadkat 30.08.2018 23:16

Сделайте что-нибудь вроде:

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

Это не помешает его загрузке в браузере.

UnkwnTech 03.01.2009 21:21

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

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

Я считаю, что было бы лучше использовать .inc.php, и это обычная практика

Lis 16.12.2019 12:37

На самом деле я советую использовать все эти лучшие практики.

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

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

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

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

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

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

Akoi Meexx 08.06.2011 20:40

Я впервые увидел, что кто-то это придумал. Я не знаю почему, потому что он кажется настолько самодостаточным, насколько это возможно, и он напрямую измеряет то, что вы действительно хотите знать (включено ли оно или нет), а не измеряет что-то, что считается связанным (например, определенная константа или определенное место запрещено .htaccess). Красивый.

Jimbo Jonny 08.08.2012 16:34

Это действительно здорово, потому что использование .htaccess для блокировки всех файлов .php не всегда возможно, так как в одном каталоге могут быть файлы, которые нужно вызывать напрямую или даже с помощью javascripts. Спасибо за отличную идею!

Anuj 19.09.2012 00:55

Это работает только в PHP5 и выше. До PHP5 вы хотите снова сравнить 0 вместо 1.

jmucchiello 10.06.2013 05:26

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

whiteatom 12.07.2013 20:19

Умный. Я использую этот метод в своем приложении.

Tom 08.08.2013 03:09

Не тестировал его в pre-php5, но я полагаю, что код будет if ( count(get_included_files()) == ((version_compare(PHP_VERSION, '5.0.0', '>='))?1:0) ) exit("Direct access not permitted.");

RiA 17.01.2017 08:21

Умное решение.

Ahmet 28.09.2017 19:34

Наконец-то кто-то четко ответит на вопрос !!! просто потратил свое время на поиск ответов в течение 3 дней и каким-то образом, нашел ваш ответ и отлично поработал !!! Спасибо чувак!

Burhan Kashour 07.10.2017 21:08

Столько лет и все еще полезно;) На самом деле, мне нужно было поменять местами условие, т.е. не разрешать включение файла, разрешен только прямой доступ. Отлично работал

Sebastian Kaczmarek 04.12.2019 11:57

Такой простой, такой минималистичный, такой локальный и в то же время переносимый. Чистый.

andiOak 22.02.2021 20:05

Помимо способа .htaccess, я видел полезный паттерн в различных фреймворках, например в Ruby on Rails. У них есть отдельный каталог pub / в корневом каталоге приложения, а каталоги библиотек находятся в каталогах с тот же уровень как pub /. Примерно так (не идеально, но идею вы поняли):

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

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

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

Спустя долгое время я просто хочу прокомментировать, что модель, которую вы описываете выше, называется моделью MVC (Модель - Представление - Контроллер). Если хотите, проверьте Google и добавьте дополнительную информацию к своему ответу. Также MVC поддерживает не только приложения Ruby on Rails и ASP.NET, но и PHP (см. Lavarel, CakePHP).

user4108694 15.02.2016 14:45

Однажды у меня была эта проблема, которую решали с помощью:

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

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

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

if (preg_match ("~ globalfile \ .php ~ i", $ _SERVER ['PHP_SELF'])) {die ('<h3 style = "color: red"> Предупреждение системы безопасности устройства - прямой доступ запрещен! Ваш IP-адрес был зарегистрирован ! <h3> '); // Остановить дальнейшее выполнение} где ~ является разделителем

MarcoZen 30.11.2017 18:12

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

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

или иначе

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

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

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

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

Я нашел это неизменяемое решение только для php, которое работает как с 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.

где предполагается вводить URL в режиме CLI?

Your Common Sense 06.04.2011 17:48

Это просто для предотвращения запуска php скрипта / включения в режиме cli. Может быть полезно в проекте с несколькими разработчиками.

Ka. 06.04.2011 18:51

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

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

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

<? } ?>

Завершите это так, чтобы вывод ошибки всегда отображался в разделе тела, если вы хотите, чтобы это было так.

Я понимаю, что всем заголовкам сервера HTTP_ * нельзя доверять, поэтому вам лучше не использовать этот метод.

andreszs 03.04.2017 18:01

Вы также можете попробовать переименовать документ, к которому вы не хотите, чтобы люди могли получить к нему доступ. Вы можете, например, переименовать его в 47d8498d3w.php. Просто придумайте что-нибудь, что люди, скорее всего, не будут набирать в качестве http-запроса. Если вы включите файл с SSI или PHP, пользователь все равно не сможет увидеть имя документа.

Никогда не используйте этот метод для защиты файлов от нежелательного выполнения.

alxbrd 23.04.2012 23:36

Безопасность неизвестностью - не лучший ответ в этом случае :)

Fabien TheSolution 16.08.2013 21:44
debug_backtrace() || die ("Direct access not permitted");

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

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

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

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

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

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

define(A,true);

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

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

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

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

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

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

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

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

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

Я предлагаю:

  1. Перед любым из ваших скриптов require('ifyoulieyougonnadie.php'); (нетinclude() и как замена defined or die)
  2. В ifyoulieyougonnadie.php выполните некоторые логические операции - проверьте различные константы, вызывающий скрипт, тестирование локального хоста и т. д. - а затем реализуйте свой 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();
<?php       
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
  if (false !== strpos($url,'.php')) {
      die ("Direct access not premitted");
  }
?>

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 прекратит выполнение.

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

// Put the code in a separate file instead, say 'checkdefined.php':
defined('_DEFVAR') or exit('Restricted Access');

// Replace the same code in the include files with:
require_once('checkdefined.php');

Таким образом можно добавить дополнительный код вcheckdefined.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. Учебник здесь.

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


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-сервер получит к ним доступ, в то время как горячие ссылки запрещены для пользователя.
  • Даже если конфигурация доступа к файловой системе веб-сервера не была выполнена должным образом, этот метод предотвратит случайное открытие доступа к этим файлам.

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

мне нравится номер 2

Baim Wrong 18.04.2018 17:53

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

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

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

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

$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if ($currentFileInfo['basename'] == $requestInfo['basename']){
    // direct access to file
}
if ( ! defined('BASEPATH')) exit('No direct script access allowed');

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

Скопируйте пасту из CodeIgnitor. Это круто, но на самом деле он ничего не делает сам по себе. BASEPATHconst установлен в файле index.php, который находится внизу древовидной структуры. CI переписывает URL-адреса, поэтому в любом случае нет необходимости напрямую обращаться к скриптам.

jimasun 28.10.2016 18:37

Я знаю, что в этом нет необходимости, но если кто-то попытается это сделать

Varshaan 28.10.2016 18:43

Ранее упомянутое решение с добавлением проверки версии PHP:

    $max_includes = version_compare(PHP_VERSION, '5', '<') ? 0 : 1;
    if (count(get_included_files()) <= $max_includes)
    {
        exit('Direct access is not allowed.');
    }

Я действительно не понимаю, как это может помешать прямому доступу

Adam Lindsay 07.10.2016 17:54

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

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

Перенаправить из этого файла на другую страницу. (например, index.html)

.htaccess:

Redirect 301 LINK_TO_YOUR_PHP LINK_TO_INDEX.HTML

Я хотел ограничить доступ к файлу 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;
    }
}

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

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

<?php

function a() {
    // function body
}

function b() {
    // function body
}

То же самое относится к файлам, которые содержат только классы PHP и ничего больше.


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

  • Вы можете случайно деактивировать PHP, и в этом случае ваш сервер может отправлять содержимое файлов PHP в браузер вместо того, чтобы запускать PHP и отправлять результат. Это может привести к утечке вашего кода (включая пароли базы данных, ключи API и т. д.).
  • Файлы в веб-каталоге занимают URL-адреса, которые вы, возможно, захотите использовать для своего приложения. Я работаю с CMS, на которой не может быть страницы с именем system, потому что это будет противоречить пути, используемому для кода. Меня это раздражает.

Другие вопросы по теме