Предотвращение подделки межсайтовых запросов в приложении Spring WebFlow

Я ищу (надеюсь, простой) способ добавить CSRF для приложения, построенного на Spring WebFlow 2.

Подход, который хорошо переносится на Spring WebFlow 3 (когда он будет выпущен), является предпочтительным.


person Eric J.    schedule 03.05.2010    source источник


Ответы (2)


Самый простой способ предотвратить CSRF - это проверить референт request.getHeader("referer");, чтобы убедиться, что запрос исходит из того же домена. Этот метод описан в CSRF Prevention Sheet .

Обычно эту систему защиты CSRF можно увидеть на встроенном сетевом оборудовании с ограниченными требованиями к памяти, Motorola использует этот метод на большей части своего оборудования. Это не самая надежная защита от CSRF, защита на основе токенов лучше, но обе системы все же можно обойти с помощью xss. Самая большая проблема с защитой CSRF на основе токенов заключается в том, что на то, чтобы вернуться и исправить каждый запрос, требуется много времени, и вы, вероятно, пропустите несколько запросов.

Безопасный способ реализовать это - проверять реферер на всех входящих запросах POST и использовать POST для чувствительных функций, таких как изменение паролей, добавление учетных записей пользователей, выполнение кода, внесение изменений в конфигурацию. GET следует использовать только для навигации или поиска, в основном GET безопасен для всего, что не вызывает изменения состояния.

Убедитесь, что вы протестируете свой сайт с помощью сканера xss.

person rook    schedule 04.05.2010
comment
Обратите внимание, что у некоторых опытных пользователей заголовки referer отключены (по соображениям конфиденциальности) и что вы должны быть осторожны с закладками (хотя людям действительно не следует добавлять в закладки страницы POST), обязательно перенаправьте браузер на другую страницу после обработки POST-данные. - person Boy Baukema; 24.10.2011
comment
Я знаю, что этот пост старый, но он стал одним из лучших в Google для моего поиска. Пожалуйста, не следуйте этому совету. Заголовки Referer поддаются подделке. Пожалуйста, просмотрите это для получения дополнительной информации: stackoverflow.com/questions/1413930/ - person John.Larison; 24.08.2012
comment
@ John.Larison Да, очень легко обмануть вашего реферера в вашем собственном браузере, однако это невозможно сделать при атаке CSRF. См. Шпаргалку по предотвращению ошибок OWASP CSRF и воздерживайтесь от распространения явно неверной информации. - person rook; 25.08.2012
comment
Сложность в том, что вы хотите исключить некоторые страницы из такой проверки. Для наших приложений, не относящихся к Web-Flow, мы делаем это, исключая прямые URL-адреса страниц. Но с Web Flow все страницы имеют один URL. - person dbreaux; 25.10.2017
comment
@dbreaux, если все страницы используют один и тот же домен, вы можете предотвратить использование доменов, принадлежащих злоумышленникам, в пользовательских сеансах с помощью CSRF, просто проверив референт или источник. - person rook; 26.10.2017
comment
@rook, если я чего-то не упускаю, дело в том, что я хочу разрешить / myapp / flow1 с любым referer / origin в начале потока. Закладки и результаты поиска являются законными источниками запуска потока. Но тогда я не хочу, чтобы в последующих запросах к / myapp / flow1 был другой референт. Поэтому мне нужно выполнить эту проверку не на уровне URL-адреса. - person dbreaux; 26.10.2017
comment
Однако, размышляя об этом дальше, я не уверен, насколько открыты потоки ... ключи выполнения, конечный автомат ... post-redirect-get - person dbreaux; 26.10.2017
comment
@dbreaux CSRF - одна из самых распространенных уязвимостей в сети прямо сейчас, потому что почти каждая платформа уязвима по умолчанию. Как разработчику вам не нужно понимать СОП, чтобы писать приложения, и легко аннулировать защиту, которую обеспечивает СОП. - person rook; 27.10.2017
comment
Я, по-видимому, не проясняю свою главную мысль. / myapp / flow1 иногда может разрешить любой реферер вообще, иногда нет. Таким образом, любое исправление, которое рассматривает это, не может быть просто основано на URL-адресе, как мы хотели сделать это для других приложений, не относящихся к Web Flow. - person dbreaux; 27.10.2017

У OWASP есть хорошее руководство по предотвращению атак CSRF, которое можно найти здесь:

Проверить заголовок Referer, безусловно, проще всего, и неплохо было бы хотя бы регистрировать экземпляры, в которых Referer является сторонним или пустым. Однако есть несколько недостатков, которые делают использование одного реферера ненадежным:

  • Корпоративные брандмауэры могут удалять заголовок referer по соображениям конфиденциальности
  • Ссылка не отправляется при переходе с HTTPS на HTTP
  • В атаках CFRF обычно сложно "подделать" реферера, но это может быть done с использованием тегов meta-refresh.

К счастью, 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.

person Barry Pitman    schedule 10.11.2011