Комментарии 52
$time = time();
$token = md5(SECRET_KEY . $userData . $time) . ':' . $time;
Как проверить такой токен, думаю, понятно.
$time = time();
$secretKey = "33Sht?U<up-~f=>@xy8sah3uwA?T(<E8gE92vh5]rs4M3%-EbX,u9SqCk6jQ)}-J";
// $userData тоже может содержать неизвестные злоумышленнику данные.
// Вы свой числовой id на хабре знаете?
$token = md5($secretKey . $userData . $time) . ':' . $time;
Хорошо, я забыл, что SECRET_KEY не пароль и может быть длинным)
Flacker ниже уже указал на необходимость использования HMAC в подобных решениях.
В связи с быстрой природой хэширующего алгоритма не рекомендуется использовать эту функцию для обеспечения безопасности паролей.
http://php.net/manual/ru/function.md5.php
Вместо md5 рекомендуется использовать password_hash
Используемая хеш-функция — дело личное. От её выбора будет зависеть скорость генерации токена.
Конечно, при прочих равных, подписать быстрее, чем зашифровать.
Предположим что я захожу на сайт good.com в результате которого мне в куки записывается номер сессии и csrf токен. Дальше я в новой вкладке открываю bad.com, который делает запрос к good.com и так как у меня в куках есть валидные номер сессии и валидный csrf, то запрос успешно выполняется.
Вопрос — где же тут защита?
В целом, всё сводится к тому, что, кроме данных в сookies, необходимо послать данные о текущем CSRF-токене вторым путём. Это может быть post-data (для форм) или доп. заголовок.
Если вы говорите о подходе Synchronizer Tokens, то тут токен-эталон просто храним на сервере (в данных сессии), а токен-валидатор посылаем клиенту например в header или, если шаблон генерируется на сервере, прямо в html'e.
Т.е. при таком подходе явно хранить в cookie CSRF-токен не нужно.
Таким образом, в запросе с другого ресурса будет ID сессии, но не будет самого CSRF-токена, так как он не должен приходить внутри cookies.
P.S. Если не очень понятна идея, то говорите, не стесняйтесь, я попытаюсь написать подробнее.
Поэтому я и не понимаю данный вид защиты с помощью csrf токена хотелось бы узнать, где я ошибаюсь.
Пока я вижу только один метод — https плюс фиксация идентификатора сессии на идентификаторе самого https соединения. Тогда у нас на каждую закладку будет своя сессия и соответственно новая сессия в новом окне, плюс не нужно возиться с токенами.
Автор пропустил Same-Origin-Policy. Если SOP настроен не правильно, на пример "Access-Control-Allow-Origin: *
" то любая CSRF защита будет в пустую. По-умолчанию SOP только Same-Origin, так что если вы не настраиваете хедер в ручную, проблем у вас не должно быть.
Слишком категорично. Есть методы попроще.
1) Можно не использовать POST. Атаковать PUT, DELETE, PATCH невозможно без специальных условий.
2) «JS приложения обычно присылают XHR запросы с header (X-CSRF-Token), содержащим токен.». Если вы все равно требуете кастомный хедер от клиента, не проще ли просто принимать саму сессию в кастомном хедере, а не куки?
в чем проблема атаковать put, delete и patch? их точно так же можно послать используя js в браузере
А чего бояться? XSS? Ну если есть XSS, то у вас и так все плохо.
Возможность угнать сессию на порядок снижает требуемую квалификацию взломщика, кроме того нестандартных сайтах угон сессии работает быстрее и оставляет меньше следов.
Присоединяюсь. Я довольно часто использую только проверку на X-Requested-With — дешево, сердито.
Чем это грозит?
Конечно, потенциально это может поломать работу сайта, если между сайтом и клиентом есть некий прокси, который режет этот заголовок. Но в реальности я пока с такой проблемой не сталкивался.
Но есть уточнение, что такой вид защиты был уязвим с использованием Flash. И прилагается ссылка на репорт об уязвимости на Vimeo: https://hackerone.com/reports/44146
Таким образом, по версии OWASP, для обеспечения необходимого уровня защиты необходимо дополнительно проверять заголовки Origin и Referer (впрочем, как и при любом другом методе).
Т.е., на сегодняшний день, при условии наличия у пользователя новейшего софта, этот вид защиты действительно хорош. Он включает в себя все плюсы stateless и при этом требует минимум усилий на реализацию.
Другой вопрос, а у всех ли пользователей софт действительно новейший… (http://caniuse.com/#search=CORS)
В интернетах можно увидеть разные мысли на тему такой защиты.
А по поводу CORS, нужно понимать, что сам по себе он не предоставляет защиты от CSRF. Вот, например, ответ на SO о том, почему CORS не совсем верно интерпретируют: http://security.stackexchange.com/a/97938
В статье предложил, как можно синхронизировать:
Синхронизация токенов между табами может быть реализована с использованием localStorage и его StorageEvent
Если вы пишете свой Web-Сервис в соотвествии со стандартом RFC7231, то ...
… то надо отказаться от любых кук. Авторизацию нужно проводить через выдачу токена, который в дальнейшем должен добавляться ко всем запросам как параметр.
В таком случае можно забыть про CSRF, XSS и другие страшные слова, а также смело прописать Access-Control-Allow-Origin: *. Если у злоумышленника нет токена — он ничего не сможет сделать. А если у него есть токен — значит, он никакой не злоумышленник, а валидный юзер.
Авторизацию нужно проводить через выдачу токена, который в дальнейшем должен добавляться ко всем запросам как параметр.
А идентификатор сессии разве не является подобным токеном?
Хотя по тому же OpenID Connect можно использовать ReferenceTokens + интроспекцию.
Идентификатор сессии при передаче через куки подвержен CSRF-атаке: злоумышленнику не обязательно знать его чтобы отправить, браузер сам его подставляет.
Если не завязываться на магию кук в браузере — то и вектор атаки пропадает.
Вариант с заголовками хороший, но не универсальный. Понятно что эта неуниверсальность касается процентов 5 случаев, но нет гарантии что завтра заказчик не захочет именно эту экзотику у себя на сайте.
Дырой в безопасности это становится когда идентификатор сессии оказывается в адресной строке. Для AJAX-запросов такой проблемы нет.
О каком CSP в веб-сервисе речь? CSP применяется в html, а веб-сервис должен работать только с json или xml.
А о каком CSRF тут обсуждение идет если это просто сервис?
Вот именно это я у вас и спросил!
Вроде как обсуждается связка — страница в браузере + REST сервис.
В случае когда страница на сервере — статическая и вся динамика реализуется на стороне браузера, CSP при прямых руках не требуется (но и не помешает).
Уникальный токен для каждой операции
Действует единожды
Я правильно понимаю, stateless решения не удовлетворяют этим требованиям?
И насколько вообще эти требования критичны?
Кто бы перевел всю статью на OWASP, было бы круто
Методы защиты от CSRF-атаки