Подтвердить что ты не робот

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

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

http://mysite.com/vote/25

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

http://mysite.com/vote/30

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

Я прочитал объяснение

4b9b3361

Ответ 1

Это может стать примером 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.

Ответ 2

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

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