Предотвращение атак XSRF и CSRF в ASP.NET MVC и на веб-страницах

по Рик Андерсон (

Подделка межсайтовых запросов (также известная как XSRF или CSRF) — это атака на веб-приложения, с помощью которых вредоносный веб-узел может повлиять на взаимодействие между браузером клиента и веб-сайтом, которому доверяет этот браузер. Эти атаки становятся возможными, так как веб-браузеры автоматически отправляют маркеры проверки подлинности при каждом запросе к веб-сайту. Типичный пример – файл cookie для проверки подлинности, например билет проверки форм ASP.NET. Однако веб-сайты, использующие любой постоянный механизм проверки подлинности (например, проверку подлинности Windows, базовый и т. д.), могут быть нацелены на эти атаки.

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

Дополнительные сведения см. в статье Open Web Application Security Project(OWASP) XSRF.

Анатомия атаки

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

HTTP/1.1 200 OK
Date: Mon, 18 Jun 2012 21:22:33 GMT
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH={authentication-token}; path=/; secure; HttpOnly;
{ Cache-Control, Content-Type, Location, Server and other keys/values not listed. }

Так как файл cookie для проверки подлинности является файлом cookie сеанса, он автоматически удаляется браузером при выходе из процесса браузера. Однако до этого времени браузер автоматически включит файл cookie с каждым запросом в WoodgroveBank.com. Теперь пользователь хочет переместить $1000 в другую учетную запись, поэтому он заполняет форму на банковском сайте, а браузер выполняет этот запрос к серверу:

POST /DoTransfer HTTP/1.1
Host: WoodgroveBank.com
Content-Type: application/x-www-form-urlencoded
Cookie: .ASPXAUTH={authentication-token}
toAcct=12345&amount=1,000.00

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

Его интерактивный банк завершен, пользователь выходит с веб-узла банка и посещает другие расположения в Интернете. Один из этих сайтов — fabrikam.com — включает следующую разметку на странице, внедренной в < IFRAME > :

<form id="theForm" action="https://WoodgroveBank.com/DoTransfer" method="post">
    <input type="hidden" name="toAcct" value="67890" />
    <input type="hidden" name="amount" value="250.00" />
</form>
<script type="text/javascript">
    document.getElementById('theForm').submit();
</script>

После чего браузер сделает запрос:

POST /DoTransfer HTTP/1.1
Host: WoodgroveBank.com
Content-Type: application/x-www-form-urlencoded
Cookie: .ASPXAUTH={authentication-token}
toAcct=67890&amount=250.00

Злоумышленник может использовать тот факт, что у пользователя по-прежнему есть действительный маркер проверки подлинности для целевого веб-сайта, и он использует небольшой фрагмент кода JavaScript, чтобы браузер мог автоматически выполнить HTTP-запрос POST к целевому сайту. Если маркер проверки подлинности по-прежнему действителен, банковский сайт запустит перенос $250 в учетную запись, выбираемую злоумышленником.

Неэффективное устранение рисков

Интересно отметить, что в приведенном выше сценарии тот факт, что доступ к WoodgroveBank.com осуществлялся по протоколу SSL и имел недостаточный файл cookie для проверки подлинности с использованием протокола SSL, чтобы предотвратить атаку. Злоумышленник может указать схему URI (HTTPS) в своем < > элементе Form, и браузер продолжит отправить файлы cookie с истекшим сроком действия на целевой сайт, если эти файлы cookie согласованы с схемой URI предполагаемой цели.

Можно сказать, что пользователь должен просто не посетить ненадежные сайты, так как посещение только надежных узлов помогает сохранить безопасность в сети. В этом нет смысла, но к сожалению, этот Совет не всегда практичен. Возможно, пользователь "доверяет" локальным веб-сайтам новостей ConsolidatedMessenger.com и переходит на этот сайт, но на этом сайте есть уязвимость XSS, которая позволяет злоумышленнику внедрить тот же фрагмент кода, который был запущен в fabrikam.com.

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

Устранение рисков XSRF среды выполнения веб-стека

Среда выполнения веб-стека ASP.NET использует вариант шаблона токена синхронизатора для защиты от атак XSRF. Общая форма шаблона токена синхронизатора состоит в том, что два XSRF токена передаются на сервер с каждым HTTP-запросом POST (в дополнение к маркеру проверки подлинности): один маркер в качестве файла cookie, а другой — как значение формы. Значения токенов, созданные средой выполнения ASP.NET, не являются детерминированными или прогнозируемыми для злоумышленника. При отправке маркеров сервер разрешает выполнение запроса, только если оба токена прошли проверку на равенство.

Токен сеанса проверки запроса XSRF хранится как файл cookie HTTP и в настоящее время содержит следующую информацию в полезных данных:

  • Маркер безопасности, состоящий из случайного 128-битного идентификатора.
    На следующем рисунке показан маркер сеанса проверки запроса XSRF, отображаемый в средствах разработчика F12 для Internet Explorer: (Обратите внимание, что это текущая реализация, которая, скорее всего, будет изменена.)

Маркер поля хранится в виде <input type="hidden" /> и содержит следующие сведения в полезных данных:

Полезные данные токенов XSRF шифруются и подписываются, поэтому вы не сможете просмотреть имя пользователя при использовании средств для проверки маркеров. Если веб-приложение предназначено для ASP.NET 4,0, службы шифрования предоставляются подпрограммыми machineKey. Encoded . Если веб-приложение предназначено для ASP.NET 4,5 или более поздней версии, службы шифрования предоставляются подсистемой machineKey. Protect , которая обеспечивает лучшую производительность, расширяемость и безопасность. Дополнительные сведения см. в следующих записях блога:

Создание маркеров

Чтобы создать маркеры XSRF, вызовите @Html.AntiForgeryToken метод из представления MVC или @AntiForgery.GetHtml () из страницы Razor. Затем среда выполнения выполнит следующие действия:

  1. Если текущий HTTP-запрос уже содержит токен сеанса Anti-XSRF (XSRF cookie _ _ рекуестверификатионтокен), маркер безопасности извлекается из него. Если HTTP-запрос не содержит токен сеанса Anti-XSRF или если не удается извлечь маркер безопасности, будет создан новый случайный токен Anti-XSRF.
  2. Токен поля Anti-XSRF создается с использованием маркера безопасности из шага (1) выше и идентификатора текущего вошедшего в систему пользователя. (Дополнительные сведения об определении удостоверения пользователя см. в разделе сценарии с поддержкой специальных возможностей ниже.) Кроме того, если настроена иантифоржеряддитионалдатапровидер , среда выполнения вызывает свой метод жетаддитионалдата и включает возвращенную строку в маркер поля. (Дополнительные сведения см. в разделе о конфигурации и расширяемости .)
  3. Если на шаге (1) был создан новый токен Anti-XSRF, будет создан новый маркер сеанса, содержащий его, который будет добавлен в коллекцию исходящих файлов cookie HTTP. Токен поля из шага (2) будет заключен в <input type="hidden" /> элемент, а эта разметка HTML будет возвращаемым значением Html.AntiForgeryToken() или AntiForgery.GetHtml() .

Проверка токенов

Чтобы проверить входящие маркеры XSRF, разработчик включает атрибут ValidateAntiForgeryToken на своем действии или контроллере MVC или вызывает @AntiForgery.Validate() его со страницы Razor. Среда выполнения выполнит следующие действия:

  1. Выполняется чтение токена входящего сеанса и маркера поля, который извлекается из каждого токена XSRF. Токены Anti-XSRF должны быть идентичными на шаге (2) в подпрограмме создания.
  2. Если текущий пользователь прошел проверку подлинности, его имя пользователя сравнивается с именем пользователя, хранящимся в маркере поля. Имена пользователей должны совпадать.
  3. Если настроена иантифоржеряддитионалдатапровидер , среда выполнения вызывает метод валидатеаддитионалдата . Метод должен возвращать логическое значение true.

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

Условия сбоя

Начиная с среды выполнения веб-стека ASP.NET версии 2, любые хттпантифоржерексцептион , созданные во время проверки, будут содержать подробные сведения о том, что пошло не так. В настоящее время определены следующие условия сбоя:

  • Маркер сеанса или маркер формы отсутствует в запросе.
  • Маркер сеанса или формы не читается. Наиболее вероятной причиной этого является ферма, на которой выполняются несовпадающие версии среды выполнения веб-стека ASP.NET или ферма, < > в которой элемент machineKey в Web.config отличается между компьютерами. Для принудительного применения этого исключения можно использовать такой инструмент, как Fiddler, с помощью токена Anti-XSRF.
  • Маркер сеанса и маркер поля были переключены.
  • Маркер сеанса и маркер поля содержат несовпадающие маркеры безопасности.
  • Имя пользователя, внедренное в маркер поля, не соответствует имени пользователя текущего вошедшего в систему пользователя.
  • Метод иантифоржеряддитионалдатапровидер. валидатеаддитионалдата вернул значение false.

Средства защиты от XSRF также могут выполнять дополнительную проверку во время создания или проверки маркера, а сбои во время этих проверок могут привести к возникновению исключений. Дополнительные сведения см. в разделах WIF/ACS/проверка подлинности и Конфигурация и расширяемость на основе утверждений.

Сценарии с специальной поддержкой

анонимная аутентификация;

Система защиты от XSRF содержит специальную поддержку для анонимных пользователей, где "Anonymous" определяется как пользователь, где свойство IIdentity. Authenticator возвращает значение false. Сценарии включают в себя предоставление защиты XSRF для страницы входа (перед проверкой подлинности пользователя) и пользовательские схемы проверки подлинности, в которых приложение использует механизм, отличный от IIdentity , для идентификации пользователей.

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

WIF, ACS и аутентификация на основе утверждений

Как правило, классы IIdentity , встроенные в .NET Framework, имеют свойство, которое IIdentity.Name достаточно для уникальной идентификации конкретного пользователя в определенном приложении. Например, FormsIdentity.Name возвращает имя пользователя, хранящееся в базе данных членства (уникальное для всех приложений в зависимости от этой базы данных), WindowsIdentity.Name возвращает доменное удостоверение пользователя и т. д. Эти системы обеспечивают не только проверку подлинности; Они также указывают пользователей на приложение.

С другой стороны, проверка подлинности на основе утверждений не обязательно требует идентификации конкретного пользователя. Вместо этого типы ClaimsPrincipal и ClaimsIdentity связаны с набором экземпляров заявок , в котором Индивидуальные утверждения могут иметь значение "более 18 лет возраста" или "является администратором". Так как пользователь не был определен, среда выполнения не может использовать свойство ClaimsIdentity.Name в качестве уникального идентификатора для этого конкретного пользователя. В реальных примерах команда ClaimsIdentity.Name возвращает значение NULL, возвращает понятное (отображаемое) имя или, в противном случае, возвращает строку, которая не подходит для использования в качестве уникального идентификатора для пользователя.

Многие из развертываний, использующих проверку подлинности на основе утверждений, в частности используют службу контроля доступа Azure (ACS). ACS позволяет разработчику настраивать отдельных поставщиков удостоверений (например, ADFS, поставщика учетных записей Майкрософт, поставщиков OpenID Connect, таких как Yahoo! и т. д.), а поставщики удостоверений возвращают идентификаторы имен. Эти идентификаторы имен могут содержать личные сведения (PII), такие как адрес электронной почты, или анонимно, например частный личный идентификатор (PPID). Независимо от этого, кортеж (поставщик удостоверений, идентификатор имени) достаточно подходит как соответствующий маркер отслеживания для конкретного пользователя при просмотре сайта, поэтому среда выполнения веб-стека ASP.NET может использовать кортеж вместо имени пользователя при создании и проверке маркеров поля Anti-XSRF. Конкретные URI для поставщика удостоверений и идентификатор имени:

  • https://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider
  • http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier

(Дополнительные сведения см. на странице документации по ACS .)

При создании или проверке маркера среда выполнения веб-стека ASP.NET будет выполнять привязку к типам:

  • Microsoft.IdentityModel.Claims.IClaimsIdentity, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 (Для пакета SDK для WIF.)
  • System.Security.Claims.ClaimsIdentity (Для .NET 4,5).

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

Проверка подлинности OAuth/OpenID Connect

Наконец, средство борьбы-XSRF имеет специальную поддержку для приложений, использующих проверку подлинности OAuth или OpenID Connect. Эта поддержка основана на эвристическом уровне: если текущая IIdentity.Name начинается с http://или HTTPS://, то сравнения имен пользователей будут выполняться с использованием компаратора порядковых номеров, а не компаратора OrdinalIgnoreCase по умолчанию.

Конфигурация и расширяемость

Иногда разработчикам может потребоваться более строгий контроль над поведением создания и проверки XSRF. Например, поведение по умолчанию для вспомогательных функций MVC и веб-страниц автоматически добавляет cookie-файлы HTTP в ответ нежелательно, и разработчик может сохранить маркеры в любом расположении. Существует два интерфейса API для помощи с этим:

AntiForgery.GetTokens(string oldCookieToken, out string newCookieToken, out string formToken);
AntiForgery.Validate(string cookieToken, string formToken);

Метод WebMethod принимает в качестве входных данных существующий токен сеанса проверки XSRF запроса (который может иметь значение null) и создает в качестве выходных данных новый токен сеанса проверки запроса XSRF и маркер поля. Токены — это просто непрозрачные строки без декорирования. значение формтокен для экземпляра не будет заключено в < тег входных данных > . Значение невкукиетокен может быть равно null. в этом случае значение олдкукиетокен остается действительным, и не нужно задавать новый файл cookie ответа. Вызывающий элемент GetResponse отвечает за сохранение всех необходимых файлов cookie ответа или создание необходимой разметки. сам метод GetResponse не изменит ответ как побочный результат. Метод Validate принимает входящие маркеры сеанса и поля и выполняет вышеупомянутые логику проверки.

антифоржериконфиг

Разработчик может настроить систему защиты от запуска приложения XSRF _ . Конфигурация является программной. Ниже описаны свойства статического типа антифоржериконфиг . Большинству пользователей, использующих утверждения, необходимо установить свойство Уникуеклаимтипеидентифиер.

Свойство Описание
аддитионалдатапровидер Объект иантифоржеряддитионалдатапровидер , предоставляющий дополнительные данные во время формирования маркера и использующий дополнительные данные во время проверки маркера. Значение по умолчанию — null. Дополнительные сведения см. в разделе иантифоржеряддитионалдатапровидер .
CookieName Строка, которая предоставляет имя файла cookie HTTP, используемого для хранения токена сеанса Anti-XSRF. Если это значение не задано, имя будет создано автоматически на основе развернутого виртуального пути приложения. Значение по умолчанию — null.
RequireSsl Логическое значение, определяющее, должны ли маркеры защиты XSRF отправляться через канал, защищенный SSL. Если это значение равно true, то во всех автоматически создаваемых файлах cookie будет установлен флаг "Secure", а API-интерфейсы XSRF будут вызываться из запроса, который не был отправлен через SSL. Значение по умолчанию — false.
суппрессидентитихеуристикчеккс Логическое значение, определяющее, должна ли система защиты от XSRF деактивировать поддержку удостоверений на основе утверждений. Если это значение равно true, система считает, что IIdentity.Name подходит для использования в качестве уникального идентификатора для каждого пользователя, и не будет пытаться использовать особый регистр IClaimsIdentity или клклаимсидентити , как описано в разделе " Проверка подлинности на основе WIF/ACS/claims-based ". Значение по умолчанию — false.
уникуеклаимтипеидентифиер Строка, указывающая, какой тип утверждения подходит для использования в качестве уникального идентификатора для каждого пользователя. Если это значение задано, а текущая IIdentity — на основе утверждений, система попытается извлечь утверждение типа, указанного параметром уникуеклаимтипеидентифиер, а соответствующее значение будет использоваться вместо имени пользователя при создании маркера поля. Если тип утверждения не найден, система не сможет выполнить запрос. Значение по умолчанию — null. Это означает, что система должна использовать кортеж (поставщик удостоверений, идентификатор имени), как описано выше, вместо имени пользователя.

иантифоржеряддитионалдатапровидер

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

Аналогичным образом метод валидатеаддитионалдата вызывается каждый раз при проверке маркера поля, а строка "дополнительные данные", внедренная в маркер, передается в метод. Подпрограммы проверки могут реализовать время ожидания (путем проверки текущего времени на время, которое было сохранено при создании маркера), подпрограммы проверки nonce или любую другую требуемую логику.

Разработка решений и рекомендаций по безопасности

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

Разработчики должны соблюдать осторожность, если несколько приложений размещаются в одном домене. Например, несмотря на то, что example1.cloudapp.NET и example2.cloudapp.NET являются разными узлами, между всеми узлами в домене * cloudapp.NET существует неявная связь доверия. Это неявное отношение доверия позволяет потенциально недоверенным узлам повлиять на файлы cookie друг друга (те же политики, которые УПРАВЛЯЮТ запросами AJAX, не обязательно применяются к ФАЙЛАМ cookie HTTP). Среда выполнения веб-стека ASP.NET предоставляет ряд мер по предотвращению того, что имя пользователя внедряется в маркер поля, поэтому даже если вредоносный поддомен может перезаписать маркер сеанса, он не сможет создать действительный маркер поля для пользователя. Однако при размещении в такой среде встроенные подпрограммы XSRF по-прежнему не могут защищаться от захвата сеанса или XSRF входа.

Подпрограммы XSRF в настоящее время не защищают от кликджекинга. Приложения, которые хотят защищать себя от кликджекинга, могут легко сделать это, отправив заголовок X-Frame-Options: САМЕОРИГИН с каждым ответом. Этот заголовок поддерживается во всех последних браузерах. Дополнительные сведения см. в блоге IE, в блоге SDLи в OWASP. Среда выполнения веб-стека ASP.NET может в некоторых будущих выпусках сделать так, чтобы вспомогательные приложения MVC и Web Pages Anti-XSRF автоматически задали этот заголовок, чтобы обеспечить автоматическую защиту приложений от атак.

Веб-разработчики должны убедиться, что их сайты не подвержены атакам XSS. Атаки XSS являются очень мощными, и успешная атака также нарушает защиту среды выполнения веб-стека ASP.NET от атак XSRF.

Acknowledgment (Подтверждение)

@LeviBroderick, кто написал большую часть кода безопасности ASP.NET.