Безопасность PHP-формы с рефером

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

if(getenv("HTTP_REFERER") != 'http://www.myURL.com/submitArea'){ die('don\'t be an jerk, ruin your own site'); }else{ // continue with form processing } 

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

EDIT: А если нет, то какая наилучшая практика для предотвращения отправки форм от других хостов?

Solutions Collecting From Web of "Безопасность PHP-формы с рефером"

На самом деле да, в соответствии с OWASP CSRF Prevention Cheat Sheet, в большинстве случаев проверка ссылочного файла достаточно для исправления уязвимости CSRF. Хотя тривиально обманывать референта на вашем СОБСТВЕННОМ БРАУЗЕ, его нельзя спутать с другим браузером (через CSRF), потому что он нарушает правила .

На самом деле проверка рефератора очень распространена, чтобы увидеть встроенное сетевое оборудование, где памяти недостаточно. Motorola делает это для своих кабельных модемов для серфинга. Я знаю эту первую руку, потому что я взломал их csrf, а затем они исправили ее, используя проверку реферирования. Эта уязвимость получила показатель серьезности 13,5, и, по данным Департамента внутренней безопасности, это самая опасная уязвимость CSRF, которая когда-либо была обнаружена и в первой 1000 самых опасных программных недостатков всех времен.

Nope – HTTP_REFERER может свободно подделываться на стороне клиента и не является надежным индикатором того, откуда пришел запрос.

Обновление: я неправильно прочитал часть об подделке кросс-сайтов: для этого проверка рефератора является допустимой мерой безопасности, потому что CSRF полагается на управляемые ссылки, указывающие на защищенные страницы (на которых атакуемый пользователь имеет привилегии). Пользователь @Rook правильный.

Единственное исключение – если атака может произойти из-за атакованного веб-приложения, например, путем инъекции вредоносного кода JavaScript. В этом случае проверка референта бесполезна, поскольку атака исходит из «безопасного» URL-адреса, но, возможно, это решение, основанное на сеансе или одноразовом токене , поскольку токен находится в пределах досягаемости вредоносного JavaScript и может быть легко извлекается.

Однако использование одноразового токена является предпочтительным для защиты от такого рода атак, потому что HTTP_REFERER некоторыми прокси.

Использование СЕССИИ, скорее всего, станет лучшим путем для предотвращения подачи заявок на участие в разных сайтах.

Хотя невозможно обмануть Referer в браузере другого пользователя, легко обмануть недостаток-реферер (например, с помощью мета-обновления), в дополнение к некоторым пользовательским агентам, которые вообще не отправляют Referer.

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

Referer является довольно слабым механизмом против XSRF. Гораздо лучше использовать токен для каждого пользователя / события, выданный сервером, который должен вернуться на сервер для проверки представления.

$ query = "SELECT * FROM users WHERE name = '$ name'";

Потенциальная уязвимость внедрения SQL. Используйте mysql_real_escape_string или параметризованные запросы.

input.setAttribute ('name', 'add_bar');

input.setAttribute ('значение', '');

Не используйте setAttribute для HTML. В IE есть ошибки, которые останавливают его работу в некоторых случаях, и есть некоторые атрибуты, которые не делают то, что вы думаете. Например, установка атрибута value не совпадает с настройкой свойства value . Свойство содержит текущее значение поля формы; атрибут содержит только «значение по умолчанию» для поля, в которое он будет сброшен, если используется <input type="reset"> . Это отображает свойство defaultValue . В некоторых браузерах установка значения по умолчанию также устанавливает значение, но это нестандартное и на что нельзя положиться.

Используйте свойства HTML DOM уровня 1, они оба более читабельны и более надежны:

 input.name= 'add_bar'; input.value= <?php echo json_encode(generate_session_token(), JSON_HEX_TAG); ?>; 

Используйте json_encode для создания значений для литералов JavaScript. Хотя вы можете быть уверены, что MD5-сумма не будет содержать символов, специально предназначенных для JS, таких как ' или», или </ sequence, которая заканчивает блок <script> (против которого аргумент HEX_TAG защищает), это не задание выходного шаблона знать, что может содержать токен сеанса. Это безопасный способ вывода любой строки в блок <script> .

См. Этот вопрос для подхода к созданию токенов анти-XSRF, которые не требуют дополнительного хранилища токенов в сеансе или базе данных.

Да, это безопасно

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

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

Это очень печально, потому что теперь это означает, что нет разумного способа гарантировать, что ваш сайт не защищен от CSRF.

альтернатива

Единственное, что вы действительно можете сделать, это поместить nonce в каждый аутентифицированный запрос на ваш веб-сервис. Это, однако, несколько опасно, потому что вы должны убедиться, что каждый пункт запроса в вашем веб-сервисе проверяет nonce. Тем не менее, вы можете использовать фреймворк, чтобы сделать это для вас, чтобы немного перенаправить это раздражение. Кажется, что переполнение стека использует nonces.

Однако

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

Вопреки тому, что здесь говорят бессмысленные люди, вы не можете выдать HTTP-запрос с поддельным заголовком из не-привилегированного кода браузера. Как и ожидалось, Flash смог сделать это один раз, чтобы обойти анти-csrf, который полагается на referrer, но он был исправлен. Почему он пропатчен? Поскольку HTTP RFC определяет, что такое реферер, и поэтому вам не разрешено изменять его значение в коде клиента, чтобы ваш клиент не был уверен.

Кто-то здесь даже утверждал, что апплет Java может выпускать произвольные заголовки через HTTP в другой домен, но это просто не так, потому что изолированный Java-апплет не разрешает делать какие- либо запросы, кроме домена, на котором он был загружен. Он быстро удалил свой комментарий, прежде чем кто-нибудь сможет его исправить …

Дело в точке

Веб-браузер – это HTTP-клиент. HTTP-клиент должен соответствовать HTTP-RFC; таким образом, он должен придерживаться того, что должно представлять собой RFC-заголовок referrer. Поскольку веб-браузер является HTTP-клиентом, любое приложение, встроенное в веб-браузер, не должно создавать запросы, нарушающие протокол HTTP. Дело в том, что каждое нарушение стандарта является потенциальной дырой в безопасности.

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

Фактически, вы можете использовать динамический адрес для этой формы. Например, когда пользователь переходит к вашей форме, вы пересылаете его на страницу со случайным адресом, например, http://www.something.com/form.php, отправленную на сайт http://www.something.com/form.php?13mklasdkl34123, где 13mklasdkl34123 генерируется случайным образом для каждого пользователя и магазина это в $ _SESSION. После получения формы submit вы можете проверить, что адрес реферера – это адрес, который вы создали для пользователя. Referrer может быть подделан, но динамическое обращение не может, поскольку спупер не может знать адрес, если он (индивидуально) не заходит на вашу страницу формы.