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

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

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

достаточно должен предотвратить перекрестные представления формы сайта.

Править: И в противном случае какова лучшая практика для того, чтобы препятствовать тому, чтобы формы были отправлены от других хостов?

18
задан Howard Zoopaloopa 16 May 2010 в 14:04
поделиться

6 ответов

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

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

3
ответ дан 30 November 2019 в 09:06
поделиться

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

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

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

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

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

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

Однако

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

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

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

Показательный пример

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

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

2
ответ дан 30 November 2019 в 09:06
поделиться

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

3
ответ дан 30 November 2019 в 09:06
поделиться

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

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

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

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

10
ответ дан 30 November 2019 в 09:06
поделиться

В то время как невозможно подделать 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('value', '');

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

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

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

Используйте json_encode для создания значений для литералов JavaScript. Хотя вы можете быть уверены, что MD5-сумма не будет содержать специальных для JS символов, таких как ' или \, или последовательности , которая завершает блок