У меня есть веб-сайт, на котором люди могут голосовать таким образом:
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-адрес выбран, проверить, что этот токен все еще действителен.
Основная идея будет:
http://mysite.com/vote/30?token=AZERTYUHQNWGST
Идея есть:
Также обратите внимание, что чем короче сеанс пользователя остается активным после того, как он покинул ваш сайт, тем меньше риск того, что он остается действительным, когда он посещает плохой сайт.
Но здесь вы должны выбрать между безопасностью и удобством для пользователя …
Еще одна идея (это не совсем безопасно, но помогает против парней, которые не знают, как заставить запрос POST), будет принимать только запросы POST, когда люди голосуют:
Но обратите внимание, что это не совсем безопасно: это (наверное ? ) возможно принудительно / подделать запрос POST, с небольшим количеством Javascript.
Во-первых, запрос GET не должен использоваться для изменения состояний на сервере, поэтому для вашей службы голосования я бы порекомендовал POST / PUT. Это только руководство, но более четкое.
Итак, на ваш вопрос, CSRF — это проблема клиента, поэтому не имеет значения, какой язык сервера вы используете (PHP в вашем случае). Стандартное исправление такое же и выглядит так: иметь случайное значение в URI / POST-данных и такое же значение в заголовке Cookie. Если эти совпадения, вы можете быть уверены, что нет CSRF. Здесь много информации о том, как это можно сделать, например, в StackOverflow. этот.
Удачи!
OWASP имеет CSRFGuard для PHP и ESAPI для PHP, который я написал давно для XMB -> UltimaBB -> GaiaBB.
Кажется, некоторые другие очистили этот код и учли более сильные токены:
https://www.owasp.org/index.php/PHP_CSRF_Guard
Спасибо,
Эндрю
В атаке CSRF 3 игрока
CSRF-атаки зависят от двух фактов
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>