Запретить прямой доступ к файлу, вызываемому функцией ajax - PullRequest
32 голосов
/ 18 ноября 2009

Я звоню php-код из ajax, как это:

ajaxRequest.open("GET", "func.php" + queryString, true);

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

Как запретить прямой доступ к http://mysite/func.php, но разрешить доступ к странице ajax?

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

Ответы [ 12 ]

45 голосов
/ 18 ноября 2009

Большинство запросов / каркасов Ajax должны устанавливать этот конкретный заголовок, который можно использовать для фильтрации запросов Ajax v Non-ajax. Я использую это для определения типа ответа (json / html) во многих проектах:

if( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && ( $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' ) )
{
    // allow access....
} else {
    // ignore....
} 

редактировать: Вы можете добавить это самостоятельно в свои собственные запросы Ajax со следующим в вашем коде JavaScript:

var xhrobj = new XMLHttpRequest();
xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 
11 голосов
/ 18 ноября 2009

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

7 голосов
/ 18 ноября 2009

Ммм ... вы могли бы сгенерировать одноразовый пароль при запуске сеанса, который вы могли бы сохранить в _SESSION, и добавить параметр к вашему вызову ajax, который бы передавал это повторно (что-то вроде капчи). Это будет действительно только для этой сессии.

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

4 голосов
/ 18 ноября 2009

Я хотел бы спросить, почему вы так уверены, что никто не сможет посетить этот файл напрямую. Ваше первое действие на самом деле должно заключаться в том, чтобы предположить, что люди могут посетить страницу напрямую и обойти эту возможность. Если вы по-прежнему убеждены, что хотите закрыть доступ к этому файлу, вам следует знать, что вы не можете доверять $_SERVER переменным для этого, поскольку трудно определить источники $_SERVER и значения заголовков могут быть подделаны. В некоторых тестах я обнаружил, что эти заголовки ($_SERVER['HTTP_X_REQUESTED_WITH'] & $_SERVER['HTTP_X_REQUESTED_WITH']) также ненадежны.

3 голосов
/ 12 мая 2013

Любой в этой теме, кто предлагал смотреть на заголовки, так или иначе ошибается. Все в запросе (HTTP_REFERER, HTTP_X_REQUESTED_WITH) может быть подделано злоумышленником, который не является полностью некомпетентным, включая общие секреты [1].

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

Ваш пример создает запрос GET, поэтому, я думаю, вы обеспокоены требованиями к ресурсам, указанными в запросе [2]. Вы можете выполнить несколько простых проверок работоспособности заголовков HTTP_REFERER или HTTP_X_REQUESTED_WITH в ваших правилах .htaccess, чтобы предотвратить появление новых процессов для явно ложных запросов (или глупых поисковых роботов, которые не будут слушать robots.txt), но если атакующий подделывает тем, вы захотите убедиться, что ваш процесс PHP завершается как можно раньше для неаутентифицированных запросов.

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

[2] GET-запросы в хорошо спроектированном приложении не имеют побочных эффектов, поэтому никто не сможет внести изменения на сервере. Ваши POST-запросы всегда должны проходить проверку подлинности с помощью сеанса плюс токен CSRF, чтобы их могли вызывать только прошедшие проверку пользователи. Если кто-то атакует это, это означает, что у него есть учетная запись, и вы хотите закрыть его.

2 голосов
/ 03 октября 2014

Я решил эту проблему, подготовив функцию проверки, которая делает три вещи

  1. проверка реферера $ _SERVER ['HTTP_REFERER'];
  2. проверьте http x запрос $ _SERVER ['HTTP_X_REQUESTED_WITH'];
  3. проверить источник через файл моста

если все три пройдены, вам удастся увидеть php-файл, вызванный ajax, если только один не получится, вы не получите его

Точки 1 и 2 уже объяснены, решение файла моста работает так:

Файл-файл

представьте себе следующий сценарий:

вызов страницы A.php через ajax B.php, и вы хотите запретить прямой доступ к B.php

  • 1) при загрузке страницы A.php генерируется сложный случайный код
  • 2) код копируется в файл C.txt, недоступный напрямую из Интернет (httpd защищен)
  • 3) в то же время этот код в чистом виде вылеплен в визуализированном html страницы A.php (например, как атрибут body, es:

    данные моста = "ehfwiehfe5435ubf37bf3834i"

  • 4) этот извлеченный код извлекается из javascript и отправляется через ajax отправить запрос в B.php

  • 5) Страница B.php получает код и проверяет, существует ли он в файле C.txt
  • 6) если код совпадает, код выводится из C.txt и со страницы B.php доступно
  • 7) если код не отправлен (если вы пытаетесь получить прямой доступ к B страница) или не совпадает вообще (если вы вводите старый код в ловушке или трюк с пользовательским кодом), B.php page die.

Таким образом, вы можете получить доступ к странице B только через ajax-вызов, сгенерированный из родительской страницы A. Ключ для pageB.php дается только и всегда от pageA.php

1 голос
/ 29 мая 2014

Поместите следующий код в самый верх вашего php-файла, который вызывается ajax. Он выполнит ajax-запросы, но "умрет", если будет вызван напрямую из браузера.

define('AJAX_REQUEST', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
if(!AJAX_REQUEST) {die();}

Лично я предпочитаю ничего не выводить после "die ()" в качестве дополнительной меры безопасности. Это означает, что я предпочитаю показывать «злоумышленнику» только пустую страницу, а не давать подсказки, такие как «если» или «почему», эта страница защищена.

0 голосов
/ 23 мая 2018

У меня есть упрощенная версия решения Эдоардо.

  1. Веб-страница A создает случайную строку [token] и сохраняет файл с таким именем на диске в защищенной папке (например, с .htaccess с Deny from all в Apache).

  2. Страница A передает [token] вместе с AJAX-запросом в сценарий B (в OP queryString).

  3. Скрипт B проверяет, существует ли имя файла [token] и, если это так, оно продолжается с остальной частью скрипта, в противном случае завершается.

  4. Вам также понадобится настроить скрипт очистки, например. с Cron, чтобы старые токены не накапливались на диске.

Также полезно сразу же удалить файл [token] с помощью скрипта B, чтобы ограничить количество запросов.

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

0 голосов
/ 06 января 2017

Я перепробовал много предложений, никто не решил проблему. Наконец, я защитил параметры целевого файла php, и это был единственный способ ограничить прямой доступ к файлу php. ** Размещаем php файл и устанавливаем ограничение с помощью .htaccess, вызывающего сбой Ajax-соединения на главной HTML-странице.

0 голосов
/ 06 марта 2015

Я пробовал это

1) в основном php-файле (из которого отправляется ajax-запрос) создайте сеанс с некоторым случайным значением, например $_SESSION['random_value'] = 'code_that_creates_something_random';. Необходимо убедиться, что сеанс создан выше $.post.

.

2) затем

$.post( "process_request.php", 
{ 
input_data:$(':input').serializeArray(),
random_value_to_check:'<?php echo htmlspecialchars( $_SESSION['random value'], ENT_QUOTES, "UTF-8"); ?>' 
}, function(result_of_processing) {
//do something with result (if necessary)
});

3) и в process_request.php

if( isset($_POST['random_value_to_check']) and 
trim($_POST['random_value_to_check']) == trim($_SESSION['random value']) ){
//do what necessary
}

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

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