Пример атаки CSRF (подделка межсайтовых запросов) и предотвращение переполнения стека

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

http://mysite.com/vote/25

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

http://mysite.com/vote/30

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

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

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

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

48

Решение

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

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

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

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

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

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

Основная идея будет:

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

Идея есть:

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

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

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

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

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

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

90

Другие решения

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

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

18

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

http://code.google.com/p/gaiabb-olpc/source/search?q=function+get_new_token&origq = функция + get_new_token&btnG = Поиск + Магистральные

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

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

Спасибо,
Эндрю

5

В атаке CSRF 3 игрока

  1. сайт жертвы (ваш сайт для голосования в вашем примере) [знает его залогиненные пользователи куки]
  2. ваш клиент браузер (пока он залогинен) [знает его печенье]
  3. сайт злоумышленника [Не знает cookie-файлы зарегистрированных пользователей]

CSRF-атаки зависят от двух фактов

  1. браузеры отправляют куки автоматически с каждым запросом
  2. мы зависим от файлов cookie, чтобы идентифицировать наших вошедших в систему пользователей (например: setcookie("sessionID", "0123456789ABCDEF", time()+3600); )

Если злоумышленник может на месте или другой сделать вошедшего в систему пользователя запрашивает это

// http://victim.website/vote/30

например, разместив ссылку на веб-сайте злоумышленника или отправив ее по электронной почте, браузер клиента, вошедшего в систему, отправит идентифицирующие файлы cookie (sessionID) вместе с этим запросом, что заставит веб-сайт жертвы думать, что его вошедший пользователь действительно хочет голосовать!

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

// http://victim.website/vote/30?csrfSecret=0123456789ABCDEF

Злоумышленник не знает csrfSecret параметр, который является секретом между сайтом жертвы и его клиентом (так же, как токен сеанса), поэтому у злоумышленника нет возможности создать URL, по которому он хочет подделать запрос.

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

<form method="post" action="http://victim.website/vote" >
<input type="hidden" name="vote" value="30">
<input type="hidden" name="csrfSecret" value="????? I don't know it :(">
</form>
1
По вопросам рекламы [email protected]