OWASP имеет хорошее руководство по предотвращению CSRF-атак здесь :
Проверка заголовка Referer, безусловно, самая простая и хорошая идея, по крайней мере, регистрировать случаи, когда Referer является сторонним или пустым. Однако есть несколько недостатков, которые делают использование только одного реферера ненадежным:
- Корпоративные брандмауэры могут лишить заголовок реферера по соображениям конфиденциальности
- При переходе с HTTPS на HTTP реферер не отправляется
- В атаках CFRF обычно трудно «подделать» реферера, но это может быть выполнено с использованием мета-тегов обновления.
К счастью, WebFlow позволяет легко реализовать собственный уникальный CSRF-фильтр токенов для каждого потока (вам может не понадобиться изменять какие-либо представления / формы)!
Сначала используйте FlowExectionListener для создания нового случайного токена при каждом запуске потока и сохранения его в flowScope. Затем всякий раз, когда событие сигнализируется, убедитесь, что переданный токен (представленный в качестве параметра в запросе) равен значению, сохраненному в flowScope.
Затем настройте пользовательский FlowUrlHandler, который добавляет параметр «_token» к сгенерированным URL-адресам, поэтому, если вы использовали $ {flowExecutionUrl} для ссылки на свои потоки, токен будет добавляться всякий раз, когда вы автоматически POST / GET возвращаетесь к своему потоку. Чтобы получить токен из flowScope из FlowUrlHandler, мне пришлось прибегнуть к использованию RequestContextHolder
private String retrieveToken() {
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (requestContext == null) {
return null;
}
return (String) requestContext.getFlowScope().get(CsrfTokenFlowListener.TOKEN_NAME);
}
...
Этот метод будет включать токен CSRF всякий раз, когда вы выводите $ {flowExecutionUrl} - как для GET, так и для POST, и если вы используете post-redirect-get, вы можете убедиться, что маркер CSRF не появится в URL бар.
Я бы предостерег от проверки только токенов CSRF на POST:
WebFlow и многие другие веб-фреймворки не различают GET и POST - по умолчанию вы, как правило, можете использовать GET, чтобы делать все, что вы делаете с POST, если вы сами не проверите метод запроса (что в любом случае было бы хорошей идеей) ). Так что злоумышленник, желающий обойти ваш CSRF-фильтр, просто сделает GET вместо POST.
Редактировать: Один недостаток, который следует учитывать при включении токенов CSRF в $ {flowExecutionUrl}, заключается в том, что токен CSRF, скорее всего, всегда будет отправляться как часть URL-адреса запроса (поскольку он будет частью атрибут «действия» HTML-формы), а не в теле POST. Включение конфиденциальной информации в URL-адрес запроса не очень хорошо, так как оно более вероятно будет зарегистрировано в журналах сервера / интернет-провайдера. Альтернативой является добавление скрытого ввода в каждую форму, содержащую токен CSRF, и принудительное использование его только для запросов POST.