В настоящее время я добавляю механизм защиты токенов CSRF в свое php-приложение.
Пока я читаю, единственным требованием является уникальный токен для каждого пользователя, который я генерирую с помощью random_bytes в php7.
Меня беспокоит то, что если злоумышленник отправит http-запрос через браузер пользователя, не отправит ли браузер переменную сеанса токена? (потому что у пользователя есть идентификатор сеанса, связанный с токеном).
Я храню токен внутри скрытого значения echo’d из переменной сеанса.
Например: мой токен хранится в переменной сеанса, а затем злоумышленник отправляет меня на страницу смены пароля с защитой csrf, проверка не пройдет? (У меня уже есть правильный идентификатор сеанса в файлах cookie моих браузеров).
Спасибо
Вот как работает атака CSRF:
Алиса (вольно или невольно) посещает compromised.com
compromised.com
делает HTTP-сообщение † запрос к yoursite.com
, используя форму HTML, или JavaScript, или Flash, или что угодно, что может сделать HTTP-запрос на публикацию.
<form method=post action="http://yoursite.com/change-password">
<input name=password value=666>
<input name=confirm_password value=666>
</form>
Это работает, потому что веб-браузер отправит Алису yoursite.com
сессионный файл cookie для yoursite.com
,
Из-за Политика того же происхождения, compromised.com
может отправить любые данные, которые он хочет на любой сайт, но не могу прочитать данные с других сайтов.
Вот как работает защита от CSRF:
yoursite.com
требует переменную HTTP post request _csrf_token
(или аналогичный) и сравнивает его с тем, что вы сохранили для Алисы в на стороне сервера память сеанса
Ты пишешь _csrf_token
значение в скрытый ввод в ваших HTML-формах, поэтому он автоматически отправляется с сообщениями формы из yoursite.com
compromised.com
не могу прочитать значение _csrf_token
от yoursite.com
из-за политики того же происхождения, поэтому его попытки опубликовать yoursite.com
не удастся.
<form method=post action="http://yoursite.com/change-password">
<input name=password value=666>
<input name=confirm_password value=666>
<input name=_csrf_token value="???">
</form>
† это не должно быть сообщение, но это распространено
Других решений пока нет …