Пример атаки CSRF (кросс-сайт запроса) и предотвращение в PHP

У меня есть сайт, на котором люди могут голосовать так:

http://mysite.com/vote/25 

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

 http://mysite.com/vote/30 

то голосование будет местом для него по предмету без его желания сделать это.

Я прочитал объяснение на веб-сайте OWASP , но я действительно не понимаю его

Является ли это примером CSRF и как я могу это предотвратить. Лучшее, что я могу придумать, это добавить что-то к ссылке, как хэш. Но это будет очень раздражать, чтобы положить что-то на конец всех ссылок. Нет другого способа сделать это.

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

Это может стать примером CSRF, если:

  • эта ссылка извлекается (например, с помощью <img> ) : подделка
  • с другого сайта: кросс-сайт

Например, если бы я мог вставить этот <img> в исходный код HTML stackoverflow (и я могу, поскольку stackoverflow позволяет использовать теги <img> в своих сообщениях) :

 <img src="http://mysite.com/vote/30" /> 

Вы бы просто проголосовали за этот пункт 😉

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

Основная идея:

  • При создании страницы:
    • генерировать уникальный токен
    • хранить его в сеансе пользователя
    • и поместите его в ссылки на страницу – это будет выглядеть так: http://mysite.com/vote/30?token=AZERTYUHQNWGST
  • Когда вызывается страница голосования:
    • Проверьте, присутствует ли токен в URL-адресе
    • Проверьте, присутствует ли он в сеансе пользователя
    • Если нет => не регистрировать голосование

Идея такова:

  • Токены не имеют долгого срока службы, и их трудно угадать
  • Это означает, что ваш атакующий :
    • имеет только окно в несколько минут, в течение которого его инъекция будет действительна
    • должно быть хорошо догадываться ^^
    • придется создавать другую страницу для каждого пользователя.

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

Но здесь вам нужно выбирать между безопасностью и удобством использования …

Другая идея (это не совсем безопасно, но помогает против парней не знать, как заставить запрос POST) , было бы только принимать запросы POST, когда люди голосуют:

  • Браузер отправляет запросы GET для введенных тегов
  • Поскольку этот URL-адрес модифицирует некоторые данные, в любом случае он не должен работать с GET, но только с POST

Но обратите внимание, что это не совсем безопасно: возможно (возможно?) Можно заставить / подделать POST-запрос с некоторым количеством Javascript.

Во-первых, запрос GET не должен использоваться для изменения состояний на сервере, поэтому для вашей службы голосования я бы рекомендовал POST / PUT. Это всего лишь ориентир, но один кливер.

Итак, на ваш вопрос, CSRF является проблемой клиента, поэтому не имеет значения, какой язык сервера вы используете (PHP в вашем случае). Стандартное исправление одинаков и выполняется следующим образом: иметь случайное значение в URI / POST-данных и такое же значение в заголовке Cookie. Если в этих матчах вы можете быть уверены, что нет CSRF. Существует много информации о том, как это можно сделать здесь, например, в StackOverflow. этот .
Удачи!

OWASP имеет CSRFGuard для PHP и ESAPI для PHP, которые я написал давно для XMB -> UltimaBB -> GaiaBB.

http://code.google.com/p/gaiabb-olpc/source/search?q=function+get_new_token&origq=function+get_new_token&btnG=Search+Trunk

Кажется, некоторые другие очистили этот код и допустили более сильные токены:

https://www.owasp.org/index.php/PHP_CSRF_Guard

спасибо, Андрей