Вторая серия безопасности внешнего интерфейса: как предотвратить атаки CSRF?

внешний интерфейс сервер Безопасность браузер

задний план

С быстрым развитием Интернета информационная безопасность стала одним из приоритетов предприятий, а внешний интерфейс представляет собой базу с высоким уровнем риска, которая вызывает проблемы с безопасностью предприятия. В эпоху мобильного Интернета, в дополнение к традиционным проблемам безопасности, таким как XSS и CSRF, персонал переднего плана часто сталкивается с новыми проблемами безопасности, такими как перехват сети и незаконный вызов гибридных API. Конечно, сам браузер постоянно развивается и развивается, и для повышения безопасности постоянно внедряются новые технологии, такие как CSP и Same-Site Cookies, но по-прежнему существует множество потенциальных угроз, которые требуют от фронтенд-техников постоянной «проверки и заполнения». в промежутках».

Фронтальная безопасность

В последние годы, с быстрым развитием бизнеса Meituan, внешний интерфейс столкнулся со многими проблемами безопасности, поэтому он накопил большой практический опыт. Мы разобрали распространенные проблемы безопасности внешнего интерфейса и соответствующие решения и создадим серию, надеясь помочь студентам, работающим с внешним интерфейсом, постоянно предотвращать и устранять уязвимости безопасности в повседневной разработке. Эта статья является второй в серии.

Сегодня мы объясним CSRF.На самом деле, по сравнению с XSS, CSRF не кажется таким уж известным.Многие думают, что "CSRF не такой разрушительный". Это действительно так? Далее мы все же приглашаем Сяо Мина снова дебютировать.

CSRF-атака

Возникновение CSRF-уязвимости

По сравнению с XSS, CSRF, похоже, не имеет такой большой репутации, и многие люди считают CSRF «менее разрушительным». Это действительно так?

Затем Сяомин приглашается появиться~~

Трагедия Сяо Мина

В этот день однокласснику Сяо Мина было скучно, и он украл его электронные письма Gmail. Большинство из них — это непитательные уведомления, проверочные коды, записи чатов и тому подобное. Но одно электронное письмо привлекло внимание Сяо Мина:

甩卖比特币,一个只要998! !

Конечно, умный Сяо Мин знал, что это, должно быть, лжец, но он все равно вмешался с любопытством (не имитировать). Конечно же, это была просто пустая страница, на которой ничего не было, и Сяо Мин разочарованно закрыл страницу. Кажется, ничего не происходит...

Под этим спокойным видом хакерская атака удалась. В Gmail Сяомина было тайно установлено правило фильтрации, которое автоматически перенаправляло все электронные письма на адрес hacker@hackermail.com. Сяо Мин продолжал просматривать свои электронные письма, но он не знал, что его электронные письма пересылались в почтовый ящик хакера, как дикая лошадь.

Вскоре после этого Сяо Мин узнал, что его доменное имя было перенесено. Невежественный Сяо Мин думал, что срок действия доменного имени истек, и он забыл продлить плату, пока однажды другая сторона не предложила цену выкупа в размере 650 долларов, и Сяо Мин начал чувствовать, что что-то не так.

Сяо Мин тщательно проверил передачу доменного имени.У другой стороны есть свой проверочный код, а проверочный код доменного имени существует только в его собственном почтовом ящике. Сяо Мин в тот день вспомнил о странной ссылке и, открыв ее, перепроверил исходный код «пустой страницы»:

<form method="POST" action="https://mail.google.com/mail/h/ewt1jmuj4ddv/?v=prf" enctype="multipart/form-data"> 
    <input type="hidden" name="cf2_emc" value="true"/> 
    <input type="hidden" name="cf2_email" value="hacker@hakermail.com"/> 
    .....
    <input type="hidden" name="irf" value="on"/> 
    <input type="hidden" name="nvp_bu_cftb" value="Create Filter"/> 
</form> 
<script> 
    document.forms[0].submit();
</script>

Эта страница будет отправлять запрос на публикацию в Gmail всякий раз, когда она открывается. В запросе выполняется команда «Создать фильтр», и все письма перенаправляются на «hacker@hakermail.com».

Поскольку Сяомин только что вошел в Gmail, этот запрос отправляется с учетными данными Сяомина для входа (Cookie). Бэкэнд Gmail получает запрос и проверяет, что учетные данные Сяомина действительно есть, поэтому Сяомин успешно настраивает фильтр.

Хакеры могут просматривать все электронные письма Сяо Мина, включая личную информацию, такую ​​как коды подтверждения домена в электронных письмах. Получив проверочный код, хакер может попросить поставщика услуг доменных имен сбросить ему доменное имя.

Сяо Мин быстро открыл Gmail, нашел фильтр и удалил его. Однако просочившиеся электронные письма, доменные имена, которые были переданы, уже невозможно восстановить...

Это трагический опыт Сяо Мина. И «щелкните хакерскую ссылку, все электронные письма украдены» не выдумка, прототипом этого инцидента является CSRF-уязвимость Gmail в 2007 году:

Woohoo. Дэвид AI Rey.com/Google-G продает…

Конечно, эта уязвимость была устранена Gmail в настоящее время, пожалуйста, не паникуйте, если вы используете Gmail.

Что такое CSRF

CSRF (Подделка межсайтовых запросов) Подделка межсайтовых запросов: Злоумышленник побуждает жертву войти на сторонний веб-сайт и на стороннем веб-сайте отправляет межсайтовый запрос на атакуемый веб-сайт. Используя регистрационные данные, которые жертва получила на атакованном веб-сайте, аутентификация пользователя в фоновом режиме обходится, и достигается цель выдачи себя за пользователя для выполнения операции на атакуемом веб-сайте.

Типичная CSRF-атака имеет следующие процедуры:

  • Жертва входит в a.comи сохраняет учетные данные для входа (файлы cookie).
  • Злоумышленники заманивают жертв на b.com.
  • b.comКa.comОтправка запроса на:a.com/act=xx. Браузер ...
  • Получив запрос, a.com проверяет запрос и подтверждает, что это учетные данные жертвы, принимая его за запрос, отправленный самой жертвой.
  • a.com выполнил act=xx от имени жертвы.
  • После завершения атаки злоумышленник выдает себя за жертву без ее ведома и заставляет a.com выполнять свою собственную определенную операцию.

Несколько распространенных типов атак

  • ПОЛУЧИТЬ тип CSRF

Использование CSRF типа GET очень просто, требуется только один HTTP-запрос, и обычно он используется следующим образом:

 <img src="http://bank.example/withdraw?amount=10000&for=hacker" > 

После того, как жертва зайдет на страницу, содержащую этот img, браузер автоматическиhttp://bank.example/withdraw?account=xiaoming&amount=10000&for=hackerСделайте HTTP-запрос. bank.example получит перекрестный запрос, содержащий данные для входа жертвы.

  • CSRF типа POST

Этот тип CSRF обычно эксплуатируется с использованием автоматически отправляемой формы, например:

 <form action="http://bank.example/withdraw" method=POST>
    <input type="hidden" name="account" value="xiaoming" />
    <input type="hidden" name="amount" value="10000" />
    <input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script> 

После посещения страницы форма будет автоматически отправлена, что эквивалентно имитации выполнения пользователем операции POST.

Атаки типа POST, как правило, немного более строгие, чем GET, но все же менее изощренные. Любой личный веб-сайт, блог или веб-сайт, загруженный хакерами, может быть источником атаки, и внутренний интерфейс не может полагаться только на разрешение POST.

  • Тип ссылки CSRF

CSRF типа ссылки не является распространенным явлением.По сравнению с двумя другими случаями, когда пользователи открывают страницу и попадают в ловушку, этот тип CSRF требует, чтобы пользователь щелкнул ссылку для срабатывания. Этот тип обычно встраивает вредоносные ссылки в изображения, размещенные на форумах, или побуждает пользователей в виде рекламы.Злоумышленники обычно обманом заставляют пользователей щелкать преувеличенными словами, такими как:

  <a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
  重磅消息!!
  <a/>

Поскольку пользователь ранее входил на доверенный веб-сайт А и сохранял статус входа, до тех пор, пока пользователь активно посещает вышеуказанную страницу PHP, атака успешна.

Особенности CSRF

  • Атаки, как правило, запускаются на сторонние веб-сайты, а не на атакуемый веб-сайт. Скомпрометированный веб-сайт не может предотвратить атаку.
  • Атака использует учетные данные жертвы для входа на атакуемый веб-сайт, чтобы выдать себя за жертву для выполнения операций, вместо того, чтобы напрямую красть данные.
  • В течение всего процесса злоумышленник не может получить учетные данные жертвы для входа, а только «мошенническое использование».
  • Межсайтовые запросы можно выполнять различными способами: URL-адреса изображений, гиперссылки, CORS, отправка форм и многое другое. Некоторые методы запросов могут быть напрямую встроены в сторонние форумы и статьи, которые трудно отследить.

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

Стратегия защиты

CSRF обычно инициируется со стороннего веб-сайта, и атакуемый веб-сайт не может предотвратить атаку и может повысить безопасность только за счет усиления возможностей защиты своего собственного веб-сайта от CSRF.

Вышеупомянутые две характеристики CSRF:

  • CSRF (обычно) происходит на сторонних доменах.
  • Злоумышленники CSRF не могут получить такую ​​информацию, как файлы cookie, а только используют их.

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

  • Блокировать доступ с неизвестных иностранных доменов
    • Обнаружение гомологии
    • Samesite Cookie
  • Информация, которую необходимо прикрепить к этому домену при отправке
    • CSRF Token
    • Двухфакторная аутентификация с помощью файлов cookie

Ниже мы подробно опишем различные методы защиты:

Обнаружение гомологии

Поскольку большинство CSRF исходят от сторонних веб-сайтов, мы напрямую запрещаем внешним доменам (или ненадежным доменным именам) отправлять нам запросы.

Итак, вопрос в том, как определить, исходит ли запрос из чужого домена?

В протоколе HTTP каждый асинхронный запрос будет содержать два заголовка, обозначающих имя исходного домена:

  • Origin Header
  • Referer Header

Эти два заголовка автоматически загружаются в большинстве случаев, когда браузер инициирует запрос, а содержимое не может быть настроено внешним интерфейсом. Сервер может определить исходный домен запроса, проанализировав доменные имена в двух заголовках.

Используйте заголовок Origin, чтобы определить исходное доменное имя.

В некоторых запросах, связанных с CSRF, поле Origin находится в заголовке запроса. Поле содержит запрошенное доменное имя (исключая путь и запрос).

Если Origin существует, вы можете напрямую подтвердить исходное доменное имя, используя поля в Origin.

Но Origin не существует в следующих двух случаях:

  • IE11 Политика того же происхождения:IE 11 не будет добавлять заголовок Origin в запросы CORS между сайтами, заголовок Referer по-прежнему будет уникальным идентификатором. Самая фундаментальная причина заключается в том, что определение гомологии в IE 11 отличается от других браузеров.Есть два основных отличия, о которых вы можете узнатьMDN Same-origin_policy#IE_Exceptions

  • 302 редирект:Источник не включается в перенаправленный запрос после перенаправления 302, поскольку источник может считаться конфиденциальной информацией из других источников. В случае перенаправления 302 он направляется на URL-адрес на новом сервере, поэтому браузер не хочет передавать источник на новый сервер.

Используйте заголовок Referer, чтобы определить исходное доменное имя

В соответствии с протоколом HTTP в заголовке HTTP есть поле Referer, которое записывает исходный адрес HTTP-запроса. Для запросов ресурсов, таких как запросы Ajax, изображения и сценарии, Referer — это адрес страницы, которая инициирует запрос. Для переходов по страницам Referer — это адрес предыдущей страницы для открытия истории страниц. Следовательно, мы можем использовать часть ссылки Origin в Referer, чтобы узнать исходное доменное имя запроса.

Этот метод не является надежным. Значение Referer предоставляется браузером. Хотя существуют четкие требования к протоколу HTTP, каждый браузер может иметь разные реализации Referer, и нет гарантии, что в самом браузере нет дыр в безопасности. . Использование метода проверки значения Referer заключается в том, чтобы полагаться на третью сторону (т.е. браузер) для обеспечения безопасности.Теоретически это не очень безопасно. В некоторых случаях злоумышленник может скрыть или даже модифицировать запрошенный им Referer.

В 2014 году рабочая группа W3C по безопасности веб-приложений выпустила проект политики Referrer Policy, в котором указывается, как браузеры должны отправлять Referrers. На данный момент большинство новых браузеров поддерживают этот проект, и мы, наконец, можем гибко управлять политикой Referer на нашем веб-сайте. В новой версии политики реферера указаны пять политик реферера: «Нет реферера», «Нет реферера при переходе на более раннюю версию», «Только происхождение», «Происхождение при перекрестном происхождении» и «Небезопасный URL-адрес». Три стратегии, существовавшие ранее: никогда, по умолчанию и всегда, изменили свои названия в новом стандарте. Их соответствующие отношения следующие:

Название политики стоимость свойства (новое) стоимость имущества (старое)
No Referrer no-Referrer never
No Referrer When Downgrade no-Referrer-when-downgrade default
Origin Only (same or strict) origin origin
Origin When Cross Origin (strict) origin-when-crossorigin -
Unsafe URL unsafe-url always

В соответствии с приведенной выше таблицей необходимо установить Referrer Policy на тот же источник.Для ссылок и ссылок одного и того же происхождения будет отправлен Referer, а значение referer — Host без пути; междоменный доступ не несет Referer. . Например:aaa.comЦитироватьbbb.comресурс, реферер отправляться не будет.

Существует три способа установки политики реферера:

  1. Установить в CSP
  2. Добавьте метатеги в шапку страницы
  3. Добавьте атрибут referrerpolicy в тег a

Вышеупомянутого много, но мы можем знать проблему: злоумышленник может скрыть Referer в своем собственном запросе. Если злоумышленник заполнит свой запрос следующим образом:

 <img src="http://bank.example/withdraw?amount=10000&for=hacker" referrerpolicy="no-referrer"> 

Тогда запрос не будет запускать атаки переноса Referer.

Кроме того, Referer недоступен или ненадежен в следующих случаях:

1. Используйте window.location.href=url для перехода к интерфейсу в IE6 и 7, и Referer будет потерян.

2. При использовании window.open в IE6 и 7 Referer также будет отсутствовать.

3. Страница HTTPS переходит на страницу HTTP, и все рефереры браузера теряются.

4. Когда вы нажимаете на Flash, чтобы перейти на другой веб-сайт, ситуация с Referer становится беспорядочной и ненадежной.

Не удалось подтвердить исходное доменное имя

Когда файл заголовка происхождения и списка не существует, как это сделать? Если происхождение и реферизатор не существует, непосредственно остановиться, особенно если вы не используете случайный токен CSRF (ссылка ниже) в качестве второй проверки.

Как заблокировать запросы чужого домена

Благодаря проверке заголовка мы можем узнать исходное доменное имя запроса. Эти исходные доменные имена могут быть собственным доменом веб-сайта, субдоменом, авторизованным сторонним доменным именем или ненадежным неизвестным доменным именем.

Мы уже знаем, относится ли запрашиваемое доменное имя к ненадежному доменному имени. Можем ли мы предотвратить атаки CSRF, заблокировав эти запросы напрямую?

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

Accept: text/html
Method: GET

Но, соответственно, запрос страницы подвергается атаке CSRF. Если ваш сайт что-то делает с текущим пользователем в GET-запросе страницы, предупреждение будет недействительным.

Например, следующий запрос страницы:

GET https://example.com/addComment?comment=XXX&dest=orderId

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

Кроме того, как упоминалось ранее, CSRF в большинстве случаев происходит от сторонних доменных имен, но это не исключает происхождения этого домена. Если злоумышленник имеет право размещать комментарии (в том числе ссылки, изображения и т. д., в совокупности именуемые пользовательским контентом) в этом домене, он может напрямую запускать атаки в этом домене. В этом случае политика одного и того же источника не может обеспечить защиту.

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

CSRF Token

Еще одна особенность CSRF, упомянутая ранее, заключается в том, что злоумышленники не могут напрямую украсть информацию о пользователе (файлы cookie, заголовки, содержимое веб-сайта и т. д.), а только обманным путем используют информацию в файлах cookie.

Причина успеха CSRF-атаки заключается в том, что сервер ошибочно рассматривает запрос, отправленный злоумышленником, как собственный запрос пользователя. Затем мы можем потребовать, чтобы все пользовательские запросы содержали токен, который не может быть получен злоумышленниками CSRF. Сервер отличает обычные запросы от запросов атаки, проверяя, содержит ли запрос правильный токен, а также может предотвращать атаки CSRF.

принцип

Стратегия защиты токена CSRF делится на три этапа:

1. Вывод CSRF-токена на страницу

Прежде всего, когда пользователь открывает страницу, сервер должен сгенерировать для пользователя токен. Токен шифрует данные с помощью алгоритма шифрования. Как правило, токен включает в себя комбинацию случайной строки и метки времени. Токен нельзя помещать в куки при отправке, иначе он будет использован злоумышленниками мошенническим путем. Поэтому в целях безопасности лучше хранить Токен в сеансе сервера, а затем использовать JS для обхода всего дерева DOM каждый раз при загрузке страницы, и добавлять Токен после всех тегов a и form в ДОМ. Это может решить большинство запросов, но для HTML-кода, динамически генерируемого после загрузки страницы, этот метод не действует, и программисту необходимо вручную добавлять Token при написании кода.

2. Запрос, отправленный страницей, содержит этот Токен.

Для запросов GET токен будет добавлен к адресу запроса, так что URL станетhttp://url?csrftoken=токензначение.Для запросов POST добавьте в конце формы:

 <input type=”hidden” name=”csrftoken” value=”tokenvalue”/>

Таким образом, Токен добавляется в запрос в виде параметра.

3. Сервер проверяет правильность токена.

Когда пользователь получает токен от клиента и снова отправляет его на сервер, сервер должен оценить действительность токена.Процесс проверки заключается в том, чтобы сначала расшифровать токен и сравнить зашифрованную строку и отметку времени.Если зашифрованная строка соответствует, и время не истекло, то этот токен действителен.

Этот метод более безопасен, чем проверка Referer или Origin ранее.Токен можно сгенерировать и поместить в Сессию, а затем Токен можно вынимать из Сессии для каждого запроса и сравнивать с Токеном в запросе, но это хлопотно часть этого метода заключается в том, как добавить токен в запрос в виде параметра. Далее в качестве примера будет использоваться Java, чтобы представить некоторую логику проверки токена CSRF на стороне сервера.Код выглядит следующим образом:

HttpServletRequest req = (HttpServletRequest)request; 
HttpSession s = req.getSession(); 
 
// 从 session 中得到 csrftoken 属性
String sToken = (String)s.getAttribute(“csrftoken”); 
if(sToken == null){ 
   // 产生新的 token 放入 session 中
   sToken = generateToken(); 
   s.setAttribute(“csrftoken”,sToken); 
   chain.doFilter(request, response); 
} else{ 
   // 从 HTTP 头中取得 csrftoken 
   String xhrToken = req.getHeader(“csrftoken”); 
   // 从请求参数中取得 csrftoken 
   String pToken = req.getParameter(“csrftoken”); 
   if(sToken != null && xhrToken != null && sToken.equals(xhrToken)){ 
       chain.doFilter(request, response); 
   }else if(sToken != null && pToken != null && sToken.equals(pToken)){ 
       chain.doFilter(request, response); 
   }else{ 
       request.getRequestDispatcher(“error.jsp”).forward(request,response); 
   } 
}

код отIBM developerworks CSRF

Значение этого токена должно быть сгенерировано случайным образом, чтобы злоумышленник не мог его угадать. Рассмотрите возможность использования класса java.security.SecureRandom приложения Java для создания достаточно длинного случайного токена. Альтернативные алгоритмы генерации включают использование 256-битного кодирования BASE64. Hash, разработчики, которые выбирают этот алгоритм генерации, должны убедиться, что случайность и уникальность используются в хэшированных данных для создания случайных идентификаторов. Как правило, разработчикам нужно создать токен только один раз для текущего сеанса. После первоначальной генерации этого токена значение будет храниться в сеансе и использоваться для каждого последующего запроса до истечения срока действия сеанса. Когда конечный пользователь делает запрос, серверная сторона должна проверить наличие и действительность токена в запросе по сравнению с токеном, найденным в сеансе. Если токен не найден в запросе или предоставленное значение не соответствует значению в сеансе, запрос должен быть прерван, токен должен быть сброшен, а событие зарегистрировано как потенциальная CSRF-атака в процессе.

Распределенная проверка

На крупных веб-сайтах использование сеанса для хранения токена CSRF создаст большую нагрузку. Доступ к одному серверному сеансу такой же. Но в современных крупных веб-сайтах у нас обычно больше одного сервера, может быть, десятки или даже сотни, и даже несколько компьютерных комнат могут быть в разных провинциях.HTTP-запросы, инициированные пользователями, обычно проходят через Ngnix и тому подобное.После балансировщика нагрузки установлен, он направляется на определенный сервер.Поскольку сессия по умолчанию хранится в памяти одного сервера, в распределенной среде несколько HTTP-запросов, отправленных одним и тем же пользователем, могут последовательно попадать на разные серверы, в результате чего HTTP запрос, инициированный позже, не может получить данные сеанса, хранящиеся на сервере с помощью предыдущего HTTP-запроса, что делает механизм сеанса недействительным в распределенной среде, поэтому токен CSRF необходимо хранить в общедоступном хранилище, таком как Redis, в распределенном кластере.

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

Значение этого токена обычно генерируется путем шифрования с использованием идентификатора пользователя, метки времени и случайного числа. Это может не только гарантировать согласованность токенов распределенных сервисов, но и гарантировать, что токены нелегко взломать.

После того, как токен успешно расшифрован, сервер может получить доступ к проанализированному значению, идентификатор пользователя и отметка времени, содержащиеся в токене, будут использоваться для проверки достоверности, идентификатор пользователя будет сравниваться с идентификатором пользователя, вошедшим в систему в данный момент, а отметка времени будет сравниваться с текущее время.

Суммировать

Токен является эффективным методом защиты от CSRF.Пока на странице нет XSS-уязвимости для утечки токена, CSRF-атака на интерфейс не может быть успешной.

Однако реализация этого метода более сложная, и необходимо писать Токен для каждой страницы (фронтенд не может использовать чистые статические страницы), каждый запрос формы и Ajax несет этот токен, а бэкэнд проверяет каждый Интерфейс и гарантирует, что токен страницы и токен запроса совпадают. Это делает эту стратегию защиты неспособной к единообразному перехвату и обработке общего перехвата, но требует добавления соответствующего вывода и проверки на каждую страницу и интерфейс. Этот метод трудоемок и может быть упущен.

Код проверки и пароль на самом деле может воспроизводить роль токена CSRF, и она более безопасна.

Почему многие банки и другие веб-сайты требуют от зарегистрированных пользователей повторно вводить свои пароли при переводе денег, есть ли смысл в этом сейчас?

Двухфакторная аутентификация с помощью файлов cookie

Хранить CSRF-токены в сеансе обременительно, и невозможно единообразно обрабатывать все интерфейсы при общем перехвате.

Тогда другой защитой является использование файлов cookie с двойной отправкой. Воспользовавшись тем фактом, что CSRF-атаки не могут получить пользовательские файлы cookie, мы можем потребовать, чтобы Ajax и запросы формы содержали значение в файле cookie.

Двойные файлы cookie используют следующий процесс:

  • Когда пользователь посещает страницу веб-сайта, добавьте в доменное имя запроса файл cookie со случайной строкой (например,csrfcookie=v8g9e4ksfhw).
  • Когда запрос инициирован к заднему концу, файл cookie удаляется, а параметры URL добавляются к URL (следующий примерPOST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw).
  • Внутренний интерфейс проверяет, соответствуют ли поля в файле cookie полям в параметрах URL-адреса, и отклоняет несоответствие.

Этот метод намного проще, чем токен CSRF. Его можно автоматизировать напрямую через методы, перехваченные фронтендом и бэкэндом. Back-end верификация тоже удобнее, просто сравните поля в запросе, и не нужно запрашивать и хранить токены.

Конечно, этот метод не применялся в больших масштабах, и его безопасность на крупных веб-сайтах все еще не так высока, как у CSRF-токена.

Поскольку любое междоменное взаимодействие приведет к тому, что передняя часть не сможет получить поля в файле cookie (в том числе между поддоменами), происходит следующее:

  • Если пользователь посещает веб-сайт какwww.a.com, а доменное имя API серверной частиapi.a.com. затем вwww.a.comвниз, передняя часть не может получить егоapi.a.comCookie, он не сможет пройти двухфакторную аутентификацию с помощью файлов cookie.
  • Таким образом, этот файл cookie для аутентификации должен быть помещен вa.com, чтобы каждый поддомен был доступен.
  • Любой поддомен можно изменитьa.comФайлы cookie под.
  • Субдомен уязвим для атаки XSS (например,upload.a.com). Хотя под этим субдоменом воровать нечего. Но злоумышленник модифицировалa.comФайлы cookie под.
  • Злоумышленник может напрямую использовать настроенный им файл cookie, а затем перенаправить пользователя, атакованного XSS, на пользователя.www.a.com, запустить CSRF-атаку.
Суммировать

Преимущества защиты от CSRF с помощью двойных файлов cookie:

  • Нет необходимости использовать сеанс, который более применим и прост в реализации.
  • Токены хранятся в клиенте и не будут давить на сервер.
  • По сравнению с токеном стоимость внедрения ниже, а проверка может быть перехвачена единообразно на фронте и бэкенде без необходимости добавления интерфейсов и страниц по одному.

недостаток:

  • Добавьте дополнительные поля в куки.
  • Если есть другие уязвимости (например, XSS), злоумышленник может внедрить файлы cookie, тогда этот метод защиты не работает.
  • Трудно изолировать поддомены.
  • Чтобы обеспечить безопасность передачи файлов cookie, лучше всего использовать этот метод защиты, чтобы убедиться, что весь сайт является HTTPS.Если использование HTTPS еще не используется, этот метод также будет рискованным.

Свойства файлов cookie на том же сайте

Способ предотвращения CSRF-атак уже включает вышеуказанные меры предосторожности. Чтобы решить эту проблему из исходного кода, Google разработал черновик для улучшения протокола HTTP, который заключается в добавлении атрибута Samesite в заголовок ответа Set-Cookie, который используется для указания, что этот файл cookie является «файлом cookie того же сайта». ". Файл cookie того же сайта может использоваться только в качестве основного файла cookie и не может использоваться в качестве стороннего файла cookie. Samesite имеет два значения атрибута, а именно Strict и Lax, которые объясняются ниже:

Samesite=Strict

Это называется строгим режимом и означает, что этот файл cookie не может использоваться в качестве стороннего файла cookie ни при каких обстоятельствах без исключения. Напримерb.comУстановлены следующие файлы cookie:

Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3

мы вa.comинициировать паруb.comДля любого запроса cookie foo не будет включен в заголовок запроса Cookie, а bar будет. Чтобы привести практический пример, если файл cookie, используемый веб-сайтом Taobao для определения того, вошел ли пользователь в систему или нет, установлен на Samesite=Strict, то после того, как пользователь щелкнет ссылку на странице поиска Baidu или даже на странице Tmall для входа Taobao, Taobao не будет входить в систему. Статус, потому что сервер Taobao не примет этот файл cookie, и любые запросы к Taobao, инициированные другими веб-сайтами, не будут приносить этот файл cookie.

Samesite=Lax

Это называется свободным режимом, который немного ослабляет ограничения по сравнению со строгим: если запрос относится к такому типу запросов (изменить текущую страницу или открыть новую страницу) и в то же время является запросом GET, этот файл cookie можно использовать как сторонний файл cookie. Например, b.com устанавливает следующие файлы cookie:

Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3

когда пользователь изa.comНажмите на ссылку, чтобы войтиb.com, cookie foo не будет включен в заголовок запроса cookie, но bar и baz будут включены, что означает, что пользователи, переходящие по ссылкам между разными веб-сайтами, не будут затронуты. Но если запрос отa.comинициированная параb.com, или переход на страницу вызван отправкой сообщения формы, полоса не будет отправлена.

Samesite, который генерирует токен, помещает его в файл cookie и устанавливает файл cookie, код Java выглядит следующим образом:

 private void addTokenCookieAndHeader(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
        //生成token
        String sToken = this.generateToken();
        //手动添加Cookie实现支持“Samesite=strict”
        //Cookie添加双重验证
        String CookieSpec = String.format("%s=%s; Path=%s; HttpOnly; Samesite=Strict", this.determineCookieName(httpRequest), sToken, httpRequest.getRequestURI());
        httpResponse.addHeader("Set-Cookie", CookieSpec);
        httpResponse.setHeader(CSRF_TOKEN_NAME, token);
    }

код отOWASP Cross-Site_Request_Forgery #Implementation example

Как мы должны использовать SamesiteCookie

Если для параметра SamesiteCookie задано значение Strict, браузер не будет передавать файл cookie ни в одном междоменном запросе, а новая вкладка не будет открываться повторно, поэтому вероятность CSRF-атак практически исключена.

Однако, если вы перейдете на поддомен или повторно откроете веб-сайт, на который вы только что попали, в новой вкладке, предыдущий файл cookie не будет существовать. Особенно, если есть веб-сайт для входа, нам нужно снова войти в систему, когда мы открываем новую вкладку для входа, или переходим на веб-сайт с именем субдомена. Для пользователей опыт может быть не очень хорошим.

Если для параметра SamesiteCookie задано значение Lax, другие веб-сайты могут использовать файлы cookie при переходе по странице, что может гарантировать статус входа пользователя при открытии страницы из подключения к внешнему домену. Но, соответственно, его защищенность также относительно невысока.

Другая проблема заключается в том, что совместимость Samesite не очень хорошая.На данном этапе, помимо поддержки от новой версии Chrome и Firefox, еще не поддерживаются Safari и iOS Safari.Похоже, что он еще не популярен на этом сцена.

Кроме того, в настоящее время SamesiteCookie имеет фатальный недостаток: субдомены не поддерживаются. Например, файл cookie, размещенный в разделе topic.a.com, не может использовать файл SamesiteCookie, размещенный в домене a.com. Это приводит к тому, что, когда наш веб-сайт имеет несколько поддоменов, SamesiteCookie нельзя использовать для хранения информации о входе пользователя в основной домен. Каждый субдомен требует от пользователя повторного входа в систему.

Короче говоря, SamesiteCookie — это возможная альтернатива проверке того же источника, но она еще не разработана, и сценарии ее применения еще предстоит увидеть.

Предотвратить использование веб-сайта

Выше я упомянул, как защитить сайт от атак. Вместо того, чтобы предотвращать атаки, CSRF-атаки могут исходить из:

  • Собственный сайт злоумышленника.
  • Веб-сайты с уязвимостями загрузки файлов.
  • Пользовательский контент, такой как сторонние форумы.
  • собственная функция комментариев атакуемого сайта и т. д.

У нас нет защиты от сайтов самих хакеров. Но в других случаях, как предотвратить использование вашего веб-сайта в качестве источника атаки?

  • Все интерфейсы загрузки строго контролируются, чтобы предотвратить любые непреднамеренные загрузки (например, HTML).
  • Добавить заголовокX-Content-Type-Options: nosniffПредотвратите, чтобы хакеры загрузки HTML-контентных ресурсов (например, изображения) разрешены на страницу.
  • Для изображений, загруженных пользователями, выполните сброс или проверку. Не используйте напрямую заполненные пользователем ссылки на изображения.
  • Когда текущие пользователи открывают ссылки, заполненные другими пользователями, их необходимо информировать о рисках (это одна из причин, по которой многие форумы не разрешают прямое размещение ссылок с внешних доменов в контенте не только для удержания пользователей, но и для также из соображений безопасности).

CSRF Другие меры предосторожности

Для передовых программистов мы можем защитить CSRF с помощью различных стратегий защиты Что мы можем сделать для повышения безопасности для QA, SRE, руководителей безопасности и других студентов?

CSRF-тест

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

  • Шаг 1. Настройте прокси-сервер браузера

CSRFTester по умолчанию использует порт 8008 на Localhost в качестве своего прокси-сервера, и если прокси-сервер настроен успешно, CSRFTester будет генерировать отладочные сообщения для всех последующих HTTP-запросов, генерируемых вашим браузером.

  • Шаг 2. Зайдите на веб-сайт с легитимной учетной записью, чтобы начать тест.

Нам нужно найти конкретную бизнес-веб-страницу, которую мы хотим протестировать на наличие CSRF. Найдя эту страницу, выберите кнопку «Начать запись» в CSRFTester и выполните бизнес-функцию; когда закончите, нажмите кнопку «Остановить запись» в CSRFTester; в нормальных условиях программное обеспечение будет проходить все запросы на текущей странице.

  • Шаг 3: Измените и подделайте запрос через CSRF

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

  • Шаг 4. Получите результаты и исправьте лазейки

Сначала необходимо выбрать «Тип отчета». Тип отчета определяет, как мы хотим, чтобы браузер-жертва отправлял ранее записанный запрос. В настоящее время существует 5 возможных отчетов: Form, iFrame, IMG, XHR и Link. После выбора типа отчета мы можем запустить только что созданный отчет в браузере и, наконец, выполнить соответствующее устранение неполадок и ремонт в соответствии с отчетом.

CSRF-мониторинг

Для более сложной системы веб-сайта вполне возможно, что в некоторых проектах, страницах и интерфейсах отсутствуют меры защиты от CSRF.

Когда происходят CSRF-атаки, как мы можем вовремя обнаружить эти атаки?

CSRF-атаки имеют очевидные характеристики:

  • Запрос на кросс-происхождение.
  • Тип MIME заголовка запроса типа GET, вероятно, является изображением, но тип MIME фактического возвращаемого заголовка — это Text, JSON и HTML.

Мы можем отслеживать все интерфейсные запросы на прокси-уровне сайта, если запрос соответствует вышеперечисленным характеристикам, можно считать, что запрос подозревается в CSRF-атаке. Мы можем напомнить руководителям соответствующих страниц и проектов проверить или пересмотреть свои политики защиты от CSRF.

Рекомендации по безопасности CSRF для отдельных пользователей

Отдельные пользователи, которые часто пользуются Интернетом, могут принять следующие меры для своей защиты:

  • Просмотр электронной почты или новостей с использованием веб-версии электронной почты также сопряжен с дополнительными рисками, поскольку просмотр электронной почты или сообщений новостей может привести к атакам вредоносного кода.
  • Старайтесь не открывать подозрительные ссылки и обязательно используйте необычные браузеры при их открытии.

Суммировать

Краткое изложение вышеуказанных стратегий защиты:

  • Стратегия автоматической защиты CSRF: обнаружение одного и того же источника (проверка источника и реферера).

  • Меры активной защиты CSRF: проверка токена или двойная проверка файлов cookie и сопоставление файлов cookie Samesite.

  • Чтобы обеспечить идемпотентность страницы, внутренний интерфейс не должен выполнять пользовательские операции на странице GET.

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

Исторический случай

WordPress CSRF-уязвимость

В марте 2012 года WordPress обнаружил уязвимость CSRF, затрагивающую WordPress версии 3.3.1. WordPress — известная платформа для ведения блогов.Эта уязвимость позволяет злоумышленникам изменять заголовок сообщения, добавлять пользователей с правами администратора и манипулировать учетными записями пользователей, в том числе Но не ограничиваясь удалением комментариев, изменением аватаров и т. д. Конкретный список выглядит следующим образом:

  • Add Admin/User
  • Delete Admin/User
  • Approve comment
  • Unapprove comment
  • Delete comment
  • Change background image
  • Insert custom header image
  • Change site title
  • Change administrator's email
  • Change Wordpress Address
  • Change Site Address

Таким образом, эта уязвимость на самом деле заключается в том, что злоумышленник сначала направляет пользователя на вход в целевой WordPress, а затем нажимает кнопку на фишинговом сайте.Кнопка на самом деле является кнопкой отправки формы, которая запускает отправку формы, добавляет пользователя с Пользователи разрешений администратора, реализованный код выглядит следующим образом:

<html> 
<body onload="javascript:document.forms[0].submit()"> 
<H2>CSRF Exploit to add Administrator</H2> 
<form method="POST" name="form0" action="http://<wordpress_ip>:80/wp-admin/user-new.php"> 
<input type="hidden" name="action" value="createuser"/> 
<input type="hidden" name="_wpnonce_create-user" value="<sniffed_value>"/> 
<input type="hidden" name="_wp_http_referer" value="%2Fwordpress%2Fwp-admin%2Fuser-new.php"/> 
<input type="hidden" name="user_login" value="admin2"/> 
<input type="hidden" name="email" value="admin2@admin.com"/> 
<input type="hidden" name="first_name" value="admin2@admin.com"/> 
<input type="hidden" name="last_name" value=""/> 
<input type="hidden" name="url" value=""/> 
<input type="hidden" name="pass1" value="password"/> 
<input type="hidden" name="pass2" value="password"/> 
<input type="hidden" name="role" value="administrator"/> 
<input type="hidden" name="createuser" value="Add+New+User+"/> 
</form> 
</body> 
</html> 

CSRF-уязвимость YouTube

В 2008 году исследователи безопасности обнаружили, что почти все действия, которые пользователи могут выполнять на YouTube, имеют уязвимости CSRF. Если злоумышленник уже добавил видео в «Избранное» пользователя, то он может добавить себя в список «Друг» или «Семья» пользователя, отправлять произвольные сообщения от имени пользователя, помечая видео как неприемлемое, автоматически делиться видео через контакты пользователя. Например, чтобы добавить видео в «Избранное» пользователя, злоумышленник может просто встроить тег IMG, как показано ниже, на любом сайте:

<img src="http://youtube.com/watch_ajax?action_add_favorite_playlist=1&video_
id=[VIDEO ID]&playlist_id=&add_to_favorite=1&show=1&button=AddvideoasFavorite"/>

Злоумышленники могли использовать уязвимость, чтобы повысить популярность видео. Например, добавьте видео в «Избранное» для достаточного количества пользователей, и YouTube отобразит это видео как «Лучшее избранное». Помимо повышения популярности видео, злоумышленники могут заставить пользователей неосознанно пометить видео как «неприемлемое», в результате чего YouTube удалит это видео.

Эти атаки могли также использоваться для нарушения конфиденциальности пользователей. YouTube позволяет пользователям разрешать просмотр определенных видео только друзьям или родственникам. Эти атаки приведут к тому, что злоумышленники добавят их в список «Друзья» или «Семья» пользователя, что позволит им получить доступ ко всем частным видео, которые в противном случае были бы ограничены пользователями из списка друзей и родственников.

Злоумышленник также может поделиться видео через все списки контактов пользователя («Друзья», «Семья» и т. д.), «обмен» означает отправку им ссылки на видео с возможностью присоединения сообщения, конечно. Ссылка в этом сообщении больше не является ссылкой на видео в полном смысле этого слова, а является оскорбительной ссылкой на веб-сайт, на которую, скорее всего, будут нажимать пользователи, что позволяет этому виду атаки распространяться вирусно.

использованная литература

следующее уведомление

В серии статей о внешней безопасности будут обсуждаться такие вопросы безопасности, как XSS, CSRF, взлом сети и гибридная безопасность. Мы обсудим захват сети в следующем выпуске, так что следите за обновлениями.

об авторе

Лю Е, главный инженер-разработчик Meituan-Dianping, отвечает за клиентский бизнес клиента, работающего на вынос.