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

php include include-guards

198982 просмотра

30 ответа

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

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

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

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

Автор: Alterlife Источник Размещён: 04.10.2019 11:38

Ответы (30)


160 плюса

Решение

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

Deny from all

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

Автор: Chuck Размещён: 03.01.2009 06:14

176 плюса

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

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

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

<?php
define('MyConst', TRUE);
?>
Автор: UnkwnTech Размещён: 03.01.2009 06:15

107 плюса

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

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

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

Автор: null Размещён: 03.01.2009 08:09

31 плюса

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

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

Автор: Eran Galperin Размещён: 03.01.2009 06:14

25 плюса

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

<FilesMatch "\.(inc)$">
    Order deny,allow
    Deny from all
</FilesMatch>
Автор: Kevin Loney Размещён: 03.01.2009 06:48

25 плюса

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

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

Автор: RiA Размещён: 27.03.2014 05:00

15 плюса

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

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

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

Автор: jmucchiello Размещён: 03.01.2009 07:00

7 плюса

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

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

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

Автор: mati Размещён: 09.03.2010 09:56

5 плюса

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

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

define(A,true);

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

defined('A') or die(header('HTTP/1.0 403 Forbidden'));
Автор: user2221806 Размещён: 28.03.2013 11:51

4 плюса

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

$including = true;

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

if (!$including) exit("direct access not permitted");
Автор: Kyle Cronin Размещён: 03.01.2009 06:12

4 плюса

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

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

или еще

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

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

Автор: Pradeesh kumar Размещён: 07.05.2010 01:11

4 плюса

debug_backtrace() || die ("Direct access not permitted");
Автор: Unirgy Размещён: 22.01.2012 11:27

4 плюса

Я хотел ограничить доступ к файлу 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;
    }
}
Автор: krasenslavov Размещён: 08.11.2017 08:27

3 плюса

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

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

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

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

Автор: bandi Размещён: 04.01.2009 01:06

2 плюса

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

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

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

Автор: Oleg Lokshyn Размещён: 08.05.2015 09:37

1 плюс

<?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
?>
Автор: Blogging Tips Размещён: 07.05.2010 01:00

1 плюс

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

if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
    header("Location: ../../index.php");
    die("...");
}
Автор: JohnRDOrazio Размещён: 18.07.2010 12:44

1 плюс

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

Автор: Ka. Размещён: 16.02.2011 04:08

1 плюс

if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };
Автор: andy Размещён: 01.10.2013 11:17

1 плюс

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

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

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

И тогда есть .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();
Автор: Just Plain High Размещён: 06.12.2013 09:48

0 плюса

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

<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
    header('HTTP/1.0 403 Forbidden');
    exit('Forbidden');
}
?>
Автор: kmkaplan Размещён: 03.01.2009 06:18

0 плюса

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

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

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

<? } ?>

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

Автор: Charming Prince Размещён: 10.09.2011 12:53

0 плюса

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

Автор: Mo Rostami Размещён: 23.04.2012 03:56

0 плюса

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

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

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

Автор: RohitG Размещён: 05.02.2013 05:30

0 плюса

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

Автор: user1391838 Размещён: 14.08.2013 02:34

0 плюса

<?php       
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
  if (false !== strpos($url,'.php')) {
      die ("Direct access not premitted");
  }
?>
Автор: Matt Bettiol Размещён: 08.03.2014 04:42

0 плюса

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

$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if($currentFileInfo['basename'] == $requestInfo['basename']){
    // direct access to file
}
Автор: talsibony Размещён: 10.09.2015 08:17

0 плюса

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

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

Автор: Varshaan Размещён: 16.10.2015 12:38

0 плюса

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

/**
 * block attempts to directly run this script
 */
if (getcwd() == dirname(__FILE__)) {
    die('Attack stopped');
}
Автор: namco Размещён: 31.01.2017 08:23

0 плюса

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

if (php_sapi_name() != 'cli') {
  throw new \Exception('This application must be run on the command line.');
}
Автор: Toskan Размещён: 17.01.2019 10:01
32x32