PHP Форма безопасности с реферером - PullRequest
18 голосов
/ 15 мая 2010

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

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

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

РЕДАКТИРОВАТЬ: И если нет, то каков наилучший способ предотвращения отправки форм с других хостов?

Ответы [ 6 ]

10 голосов
/ 15 мая 2010

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

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

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

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

3 голосов
/ 16 мая 2010

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

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

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

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

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

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

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

3 голосов
/ 16 мая 2010

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

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

3 голосов
/ 15 мая 2010

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

2 голосов

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

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

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

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

Alternative

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

Однако

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

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

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

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

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

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

0 голосов
/ 16 мая 2010

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

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