Как защитить php-скрипты?

Если у меня есть вызов AJAX для php-скрипта, например (с помощью jQuery)

$.ajax(url: "../myscript.php"); 

и myscript выглядит так:

 <?php //code that does something to db ?> 

Я хочу знать, как запретить пользователю просто перейти на example.com/myscript.php для выполнения сценария.

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

Вам просто нужно спросить себя: должно ли ваше приложение обеспечить, чтобы все запросы на myscript.php контролировались?

Если это так, вам нужно использовать какой-то токен: вы создаете токен и отправляете его клиенту (браузеру), тогда браузер должен отправить обратно токен, и вы проверяете, совпадает ли оно, прежде чем предпринимать какое-либо действие:

 <?php // somefile.php (this file serves the page that contains your AJAX call) session_start(); //... $_SESSION['token'] = createNewToken(); // creates unique tokens //add the token as a JS variable and send it back in your AJAX CALL // some where you'll have something similar to this: <script> var token = <?php echo $_SESSION['token'] ?>; $.ajax({ url: "myscript.php", data: form_data, // include the token here! //... }) 

И затем в вашем скрипте:

 <?php // myscript.php session_start(); // you can check if it's an AJAX call, if the user is logged and then the token: if (!isset($_SESSION['token')) { header("HTTP/1.0 403 Forbidden"); die("Direct access not allowed!"); } // Assuming your AJAX is a POST though you didn't tell us if (!isset($_POST['token'] || $_POST['token'] != $_SESSION['token']) { header("HTTP/1.0 400 Bad request"); die("You didn't provide a valid token!"); } // do something with your DB 

В противном случае вам просто нужно проверить, зарегистрирован ли пользователь, как обычно, с остальными вашими сценариями:

 <?php // myscript.php session_start(); // Check if logged in user if (!isset($_SESSION['loggedIn']) || !$_SESSION['loggedIn']) { header("HTTP/1.0 403 Forbidden"); die("You need to be logged in!"); } // Do something with your DB 

ПОДВОДИТЬ ИТОГИ

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

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

Запросы Ajax – это просто пользовательские запросы

Каждый XmlHTTP-запрос может быть воспроизведен и изменен (просто проверьте свою любимую консоль браузера, запишите POST или GET-запросы и проверьте, есть ли варианты воспроизведения), вы также можете попробовать модуль Live HTTP Headers (или многое другое) и захватить все, чтобы воспроизвести Это.

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

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

Небезопасные входы

Таким образом, с точки зрения безопасности каждый пользовательский ввод должен считаться небезопасным (параметры GET, данные POST, используемый url – столько приложений OMG никогда не фильтрует данные, поступающие с пути URL-адреса, файлы cookie, …)

Отфильтрованный выход

Поэтому вы можете задаться вопросом: «Как я могу сделать что-то с небезопасными входами?», Ну … вы можете. Правило состоит в том, чтобы отфильтровать все выходы. Возьмите выходной канал (хранилище базы данных, html-страницу, ответ json, файл csv) и, соответственно, избегайте ваших данных (htmlentites для HTML, json escapes для json, sql escaper или параметризованных запросов для SQL-запросов – проверьте libs–), особенно части, поступающие с пользовательского ввода, которые действительно небезопасны, как указано ранее.

Контроль доступа

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

Несколько вещей, чтобы сделать:

  • убедитесь, что это не точка входа GET (только POST, PUT, DELETE HTTP-действия должны выполнять изменения в базе данных), это предотвратит использование этого URL-адреса в теге изображения позже, загружая действие без взаимодействия с пользователем.
  • управлять сеансом пользователя , используя файлы cookie (для PHP это для вас) вы можете обмениваться некоторыми данными между несколькими HTTP-запросами, это называется сеансом. Пользовательский cookie будет использоваться для загрузки хранилища сеансов на стороне сервера, содержащих важные данные, например, является ли мой пользователь анонимным пользователем или подключенным? , Это идентификационная часть.
  • управлять страницами входа в систему, чтобы получить часть аутентификации , страницы тезисов будут снабжать сессию статусом входа в систему. Для простого решения вы также можете проверить базовую аутентификацию HTTP (файлы .htpasswd), она также будет работать для ajax, но никогда не будет использовать базовую HTTP-аутентификацию без SSL. Этот режим Http auth будет управлять идентификационными и аутентификационными частями.
  • управлять списком контроля доступа (Access Control List), как вы хотите, и использовать это, чтобы решить, может ли ваша страница ajax доступ к текущему пользователю (вы получаете пользователя из сеанса). Если нет, отправьте 403 HTTP-ответ.

Публичный доступ

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

Мы могли бы говорить о многом, но это зависит от того, что вы пытаетесь сделать. Важно:

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

как запретить пользователю просто перейти на example.com/myscript.php для выполнения сценария

С точки зрения безопасности, вызов AJAX такой же, как и пользователь, идущий на этот URL. То есть пользователь-пользователь и сценарий, который вы используете для вызова AJAX, являются частью одного и того же принципала безопасности. Если вы не доверяете пользователю доступ к скрипту PHP, вы не можете доверять JavaScript, запущенному на компьютере, управляемом пользователем.

Итак, в каких случаях могут быть отдельные принципы безопасности? Например, вы можете развернуть клиентский JavaScript на каком-то защищенном от несанкционированного доступа киоске. Таким образом, вы можете сохранить секретное значение в киоске, который будет использоваться совместно с сервером. Киоск отправил секретное значение с каждым запросом для проверки сервера.

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