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

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

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

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

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

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

 Deny from all 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

СПОСОБ 1:

Проверка включает счетчик

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

Логика:

  • PHP5 +: Проверить на> = 1
  • Другое: Проверить> = 0
  • Else: exit ()

PHP5 + считает текущую страницу включенной.


СПОСОБ 2:

Использование авторизированных интерфейсных адресов

Это делается в файле main.php, к которому пользователь может получить доступ напрямую:

 $loopbackdata=file_get_contents("http://127.0.0.1/component.php?query=string"); 

Где component.php – это файл, который вы не хотите, чтобы пользователь имел прямой доступ.


В вашем файле component.php, вверху, вы можете использовать:

 //VARS $dart="/error.php?errortype=direct_access_of_component"; //Description: Direct-Access Redirection Target //GET SOURCE OF REQUEST $src=$_SERVER['REMOTE_ADDR']; //VALIDATE SOURCE(COMPARE AGAINST AUTHORIZED FRONT-END SERVER ADDRESSES) $auth=false; switch($src){ case "localhost": case "127.0.0.1": case "192.168.0.1": $auth=true; break; default: $auth=false; } //IF NOT AUTHENTICATED, EXIT: if(!$auth){header("Location: ".$dart);exit();} //ELSE PROCEED WITH CODE 

СПОСОБ 3:

Используйте запрос GET или POST для передачи ключа авторизации в файл «component.php»,

Разбор строки с использованием php. И снова, наконец:

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

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


СПОСОБ 4:

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

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

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

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


СПОСОБ 5:

Размещение включает в безопасный каталог ВНЕ САЙТА сайта

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

 //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 поскольку ссылки будут htdocs для адресной системы веб-сайта.
  • Php-сервер обращается к файловой системе изначально и, следовательно, может обращаться к файлам на компьютере так же, как обычная программа с требуемыми привилегиями.
  • Поместив включенные файлы в этот каталог, вы можете убедиться, что php-сервер получает доступ к ним, а хотлинкинг – пользователю.

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

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

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

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

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

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

 define(A,true); 

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

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

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

 $including = true; 

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

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

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

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

или иначе

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. .htaccess и Apache
  2. defined('_SOMECONSTANT') or die('Hackers! Be gone!');

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

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

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

Я предлагаю:

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

    Я создаю свою собственную фреймворк с двумя возможными точками входа – основной index.php (структура Joomla) и ajaxrouter.php (my framework) – поэтому в зависимости от точки входа я проверяю разные вещи. Если запрос на 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(); 
 if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 

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

Я хотел напрямую ограничить доступ к файлу 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 if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') { header('HTTP/1.0 403 Forbidden'); exit('Forbidden'); } ?> 

Я нашел это 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.

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

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

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

 <? } ?> 

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

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

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

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

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

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

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

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

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

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

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

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

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