Я ищу (надеюсь, простой) способ добавить CSRF для приложения, построенного на Spring WebFlow 2.
Подход, который хорошо переносится на Spring WebFlow 3 (когда он будет выпущен), является предпочтительным.
Я ищу (надеюсь, простой) способ добавить CSRF для приложения, построенного на Spring WebFlow 2.
Подход, который хорошо переносится на Spring WebFlow 3 (когда он будет выпущен), является предпочтительным.
Самый простой способ предотвратить CSRF - это проверить референт request.getHeader("referer");
, чтобы убедиться, что запрос исходит из того же домена. Этот метод описан в CSRF Prevention Sheet .
Обычно эту систему защиты CSRF можно увидеть на встроенном сетевом оборудовании с ограниченными требованиями к памяти, Motorola использует этот метод на большей части своего оборудования. Это не самая надежная защита от CSRF, защита на основе токенов лучше, но обе системы все же можно обойти с помощью xss. Самая большая проблема с защитой CSRF на основе токенов заключается в том, что на то, чтобы вернуться и исправить каждый запрос, требуется много времени, и вы, вероятно, пропустите несколько запросов.
Безопасный способ реализовать это - проверять реферер на всех входящих запросах POST и использовать POST для чувствительных функций, таких как изменение паролей, добавление учетных записей пользователей, выполнение кода, внесение изменений в конфигурацию. GET следует использовать только для навигации или поиска, в основном GET безопасен для всего, что не вызывает изменения состояния.
Убедитесь, что вы протестируете свой сайт с помощью сканера xss.
У OWASP есть хорошее руководство по предотвращению атак CSRF, которое можно найти здесь:
Проверить заголовок Referer, безусловно, проще всего, и неплохо было бы хотя бы регистрировать экземпляры, в которых Referer является сторонним или пустым. Однако есть несколько недостатков, которые делают использование одного реферера ненадежным:
К счастью, 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 формы 'action') и никогда в теле сообщения POST. Включение конфиденциальной информации в URL-адрес запроса - это не лучший вариант, поскольку он с большей вероятностью будет зарегистрирован в журналах сервера / интернет-провайдера. Альтернативой является добавление скрытого ввода в каждую форму, содержащую токен CSRF, и обеспечение его присутствия только для запросов POST.