Автор: Анджело Меллос

В NCC Group мы заметили среди заявителей и широкой общественности некоторые распространенные заблуждения относительно подделки межсайтовых запросов (CSRF) и способов ее предотвращения. Это результат неполного понимания следующих понятий и отношений между ними:

  • Cross-Origin Resource Sharing (CORS) — политика браузера, разрешающая междоменные запросы. 1
  • Политика единого источника — механизм безопасности, предоставляемый веб-браузерами, который предотвращает доступ приложений, размещенных в двух разных доменах, к данным друг друга. 2
  • Разница между HTTP-запросами XML (XHR) и отправкой HTML-форм.

Это может привести к некоторым опрометчивым представлениям о средствах защиты от CSRF, например:

  • Этот CORS является защитой от CSRF.
  • То, что разрешение только определенных методов запроса может обеспечить надежную защиту от CSRF.
  • Что определенные заголовки Content-Type делают CSRF невозможным.

Мы рассмотрим каждый из них ниже и представим альтернативу.

CORS не является механизмом предотвращения CSRF

Совместное использование ресурсов между источниками (CORS) — это механизм, который позволяет приложениям, размещенным в двух разных доменах, совместно использовать ресурсы: важно понимать, что CORS — это ослабление политики единого источника. Когда сервер устанавливает политику CORS, он указывает браузеру изменить свое обычное поведение, чтобы разрешить отправку запросов и получение ответов сервера из разных источников. Если браузер определяет на основе заголовков, метода запроса и типа контента, что запрос не является простым запросом, то перед отправкой фактического запроса он отправит предварительный запрос OPTIONS. Браузер затем разрешит или отклонит запрос на основе политики CORS, переданной в ответе предварительной проверки. 3

Любой запрос, сгенерированный HTML-формой, обязательно будет простым запросом и никогда не будет проходить предварительную проверку. Представления формы могут быть отправлены из любого источника в любой другой источник. Браузер отобразит ответ, но при этом изменит URL-адрес (т. е. источник) на адрес отвечающего домена. Отправляющий источник запроса из другого источника не может получить доступ к ответу на отправку формы через JavaScript.

Хотя правильно настроенная политика CORS важна, сама по себе она не представляет собой защиту от CSRF. Добавление политики CORS там, где ее раньше не было, не может обеспечить дополнительную защиту от CSRF. Фактически, чрезмерно разрешительная политика CORS может подорвать некоторые попытки предотвратить CSRF, как мы увидим ниже. Кроме того, CSRF через простой запрос будет успешным или неудачным независимо от политик CORS.

Не полагайтесь на альтернативные методы HTTP

Браузеры всегда будут отправлять предварительный запрос для любого метода запроса, кроме GET, POST или HEAD. Это означает, что если сервер не обрабатывает какие-либо запросы GET или POST, это может обеспечить способ защиты от CSRF, полагаясь на ограничительный или отсутствующий заголовок Access-Control-Allow-Origin ответа перед отправкой.

Но такой подход к предотвращению CSRF сомнителен и основан на использовании информации, не предназначенной для обеспечения безопасности. Из-за этого могут возникнуть проблемы. Например, многие платформы веб-приложений предоставляют промежуточное ПО для переопределения методов. Обычно они ищут параметр строки запроса _method и изменяют метод запроса в зависимости от значения этого параметра. 4, 5 Злоумышленники могут использовать этот метод, чтобы заставить сервер принять запрос GET или POST, как если бы он была непростая просьба.

Не полагайтесь на заголовки Content-Type

Одним из условий, определяющих, является ли запрос простым запросом и, следовательно, отправляется ли предварительный запрос, является заголовок Content-Type. Если этот заголовок имеет значение, отличное от application/x-www-form-urlencoded, multipart/form-data или text/plain, то запрос проходит предварительную проверку. Таким образом, требование, чтобы все запросы имели другой тип контента, такой как application/json. This, может обеспечить средства защиты от CSRF, полагаясь на ограничительный или отсутствующий заголовок Access-Control-Allow-Origin ответа на предварительную проверку способом, аналогичным требованию определенного метода HTTP. Некоторые фреймворки могут обеспечивать защиту от CSRF, но в таких случаях отключают ее. 6

Такой подход к предотвращению CSRF также сомнителен; он также опирается на использование информации, не предназначенной для обеспечения безопасности. Изменения в функциях или политиках браузера могут подорвать такую ​​защиту. Примером этого является Navigator.sendBeacon API в Chrome. Давняя ошибка в этой функции позволяла устанавливать заголовки Content-Type, отличные от трех упомянутых выше, без запуска запроса предварительной проверки. Разработчики браузеров даже рассматривали возможность изменения поведения браузера, заставив его игнорировать заголовки Content-Type при определении необходимости отправки предварительной проверки, несмотря на последствия, которые это может иметь для приложений, которые полагаются на нее. 7

Альтернатива: токены Anti-CSRF

Более надежным и широко используемым средством предотвращения CSRF является отправка маркера, связанного с активным сеансом, с каждым запросом на изменение состояния. В случае с HTML-формами серверное приложение включает скрытый параметр, содержащий токен для конкретного сеанса. При отправке формы токен отправляется вместе с телом запроса. Перед обработкой запроса сервер проверяет, является ли полученный токен действительным и ожидаемым для текущего сеанса. Процесс очень похож на запросы XHR: может быть установлен пользовательский заголовок или параметр запроса, который имеет значение, равное токену, сгенерированному сервером. 8

Важной ошибкой, на которую следует обратить внимание, является размещение токена в URL-адресе, что обычно происходит с запросами GET, поскольку они не имеют тела. Такое поведение может привести к раскрытию значений токенов защиты от CSRF, поскольку URL-адреса могут отображаться в различных местах, включая историю браузера, файлы журналов и заголовки Referer. Поскольку запросы GET не должны выполнять действия по изменению состояния, не должно быть необходимости когда-либо отправлять токены анти-CSRF с помощью этого метода. В такой ситуации правильным подходом будет оценка того, какой метод HTTP, кроме GET, подходит для выполнения действия.

Не используйте ярлыки, когда дело доходит до CSRF

Описанные выше заблуждения могут привести к неадекватной защите от CSRF. Иногда желание избежать сложности защиты на основе токенов может сделать альтернативы более привлекательными. Но CSRF — это серьезная уязвимость, и важно использовать надежную и перспективную защиту от CSRF, поскольку использование ярлыков рано или поздно приведет к неприятным последствиям. Полное исследование средств защиты на основе токенов выходит за рамки этого поста, но подробное введение можно найти в статье Подделка межсайтовых запросов: введение в распространенную слабость веб-приложений. Кроме того, большинство фреймворков веб-приложений имеют встроенную защиту. Их следует использовать везде, где это возможно, а средства защиты на основе токенов следует выбирать в пользу альтернатив, описанных выше.

  1. https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
  2. https://en.wikipedia.org/wiki/Cross-site_request_forgery
  3. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
  4. https://github.com/expressjs/method-override
  5. http://www.rubydoc.info/gems/rack/Rack/MethodOverride
  6. http://seclists.org/oss-sec/2016/q3/51
  7. https://bugs.chromium.org/p/chromium/issues/detail?id=490015
  8. https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Synchronizer_.28CSRF.29_Tokens

Дата публикации: 5 сентября 2017 г.

Первоначально опубликовано на www.nccgroup.trust.