ASP.NET Core でのクロスサイト要求偽造 (XSRF/CSRF) 攻撃を防ぐPrevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core

Rick AndersonFiyaz Hasan上田 SmithBy Rick Anderson, Fiyaz Hasan, and Steve Smith

クロスサイト要求偽造 (XSRF または CSRF とも呼ばれます) は、web ホストアプリに対する攻撃であり、悪意のある web アプリがクライアントブラウザーとそのブラウザーを信頼する web アプリとの間の対話に影響を与える可能性があります。Cross-site request forgery (also known as XSRF or CSRF) is an attack against web-hosted apps whereby a malicious web app can influence the interaction between a client browser and a web app that trusts that browser. これらの攻撃は、web ブラウザーがすべての要求を web サイトに自動的に送信するために発生する可能性があります。These attacks are possible because web browsers send some types of authentication tokens automatically with every request to a website. この形式の悪用は、 ワンクリック攻撃 または セッション によっても知られています。これは、攻撃がユーザーの以前に認証されたセッションを利用しているためです。This form of exploit is also known as a one-click attack or session riding because the attack takes advantage of the user's previously authenticated session.

CSRF 攻撃の例を次に示します。An example of a CSRF attack:

  1. ユーザーは、 www.good-banking-site.com フォーム認証を使用してサインインします。A user signs into www.good-banking-site.com using forms authentication. サーバーはユーザーを認証し、認証を含む応答を発行し cookie ます。The server authenticates the user and issues a response that includes an authentication cookie. サイトは、有効な認証を使用して受信したすべての要求を信頼しているため、攻撃に対して脆弱です cookie 。The site is vulnerable to attack because it trusts any request that it receives with a valid authentication cookie.

  2. ユーザーが悪意のあるサイト () にアクセスして www.bad-crook-site.com います。The user visits a malicious site, www.bad-crook-site.com.

    悪意のあるサイトには、 www.bad-crook-site.com 次のような HTML フォームが含まれています。The malicious site, www.bad-crook-site.com, contains an HTML form similar to the following:

    <h1>Congratulations! You're a Winner!</h1>
    <form action="http://good-banking-site.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw">
        <input type="hidden" name="Amount" value="1000000">
        <input type="submit" value="Click to collect your prize!">
    </form>
    

    悪意のあるサイトではなく、脆弱なサイトにフォームが投稿されていることに注意して action ください。Notice that the form's action posts to the vulnerable site, not to the malicious site. これは CSRF の "クロスサイト" 部分です。This is the "cross-site" part of CSRF.

  3. ユーザーは [送信] ボタンを選択します。The user selects the submit button. ブラウザーは要求を行い、要求されたドメインの認証を自動的に含め cookie www.good-banking-site.com ます。The browser makes the request and automatically includes the authentication cookie for the requested domain, www.good-banking-site.com.

  4. 要求は、 www.good-banking-site.com ユーザーの認証コンテキストを使用してサーバー上で実行され、認証されたユーザーが実行を許可されている任意のアクションを実行できます。The request runs on the www.good-banking-site.com server with the user's authentication context and can perform any action that an authenticated user is allowed to perform.

フォームを送信するためにユーザーがボタンを選択するシナリオに加えて、悪意のあるサイトも考えられます。In addition to the scenario where the user selects the button to submit the form, the malicious site could:

  • フォームを自動的に送信するスクリプトを実行します。Run a script that automatically submits the form.
  • フォーム送信を AJAX 要求として送信します。Send the form submission as an AJAX request.
  • CSS を使用してフォームを非表示にします。Hide the form using CSS.

これらの代替シナリオでは、最初に悪意のあるサイトにアクセスしていないユーザーからの操作や入力は必要ありません。These alternative scenarios don't require any action or input from the user other than initially visiting the malicious site.

HTTPS を使用しても CSRF 攻撃を防ぐことはできません。Using HTTPS doesn't prevent a CSRF attack. 悪意のあるサイトは、 https://www.good-banking-site.com/ セキュリティで保護されていない要求を送信するのと同じように簡単に要求を送信できます。The malicious site can send an https://www.good-banking-site.com/ request just as easily as it can send an insecure request.

一部の攻撃では、GET 要求に応答するエンドポイントを対象にしています。この場合、イメージタグを使用してアクションを実行できます。Some attacks target endpoints that respond to GET requests, in which case an image tag can be used to perform the action. この形式の攻撃は、イメージを許可し、JavaScript をブロックするフォーラムサイトで共通です。This form of attack is common on forum sites that permit images but block JavaScript. GET 要求の状態を変更するアプリ (変数またはリソースが変更された場合) は、悪意のある攻撃に対して脆弱です。Apps that change state on GET requests, where variables or resources are altered, are vulnerable to malicious attacks. 状態を変更する GET 要求は安全ではありません。GET 要求の状態を変更しないことをお勧めします。GET requests that change state are insecure. A best practice is to never change state on a GET request.

cookie次の理由により、認証にを使用する web アプリに対して CSRF 攻撃が行われる可能性があります。CSRF attacks are possible against web apps that use cookies for authentication because:

  • cookieWeb アプリによって発行されたのブラウザーストア。Browsers store cookies issued by a web app.
  • 保存された cookie には、認証されたユーザーのセッションが含まれ cookie ます。Stored cookies include session cookies for authenticated users.
  • cookieブラウザーでは、アプリへの要求がブラウザー内でどのように生成されたかに関係なく、ドメインに関連付けられているすべてのを要求ごとに web アプリに送信します。Browsers send all of the cookies associated with a domain to the web app every request regardless of how the request to app was generated within the browser.

ただし、CSRF 攻撃は、を利用することに限定されません cookie 。However, CSRF attacks aren't limited to exploiting cookies. たとえば、基本認証とダイジェスト認証も脆弱です。For example, Basic and Digest authentication are also vulnerable. ユーザーが基本認証またはダイジェスト認証を使用してサインインすると、セッションが終了するまで、ブラウザーは資格情報を自動的に送信し † ます。After a user signs in with Basic or Digest authentication, the browser automatically sends the credentials until the session† ends.

†このコンテキストでは、 セッション とは、ユーザーが認証されるクライアント側のセッションを指します。†In this context, session refers to the client-side session during which the user is authenticated. サーバー側セッションや ASP.NET Core セッションミドルウェアとは無関係です。It's unrelated to server-side sessions or ASP.NET Core Session Middleware.

ユーザーは、次のように予防措置を講じて CSRF 脆弱性を防ぐことができます。Users can guard against CSRF vulnerabilities by taking precautions:

  • Web apps の使用が完了したら、サインオフします。Sign off of web apps when finished using them.
  • ブラウザー cookie を定期的にクリアします。Clear browser cookies periodically.

ただし、CSRF 脆弱性は、エンドユーザーではなく、根本的に web アプリに問題があります。However, CSRF vulnerabilities are fundamentally a problem with the web app, not the end user.

認証の基礎Authentication fundamentals

Cookieベースの認証は、一般的な認証形式です。Cookie-based authentication is a popular form of authentication. 特にシングルページアプリケーション (spa) では、トークンベースの認証システムの普及が高まっています。Token-based authentication systems are growing in popularity, especially for Single Page Applications (SPAs).

Cookieベースの認証Cookie-based authentication

ユーザー名とパスワードを使用して認証を行うと、認証と承認に使用できる認証チケットを含むトークンが発行されます。When a user authenticates using their username and password, they're issued a token, containing an authentication ticket that can be used for authentication and authorization. トークンは、 cookie クライアントが行うすべての要求に付随するとして格納されます。The token is stored as a cookie that accompanies every request the client makes. これ cookie は、認証ミドルウェアによって生成および検証され Cookie ます。Generating and validating this cookie is performed by the Cookie Authentication Middleware. ミドルウェアは、ユーザープリンシパルを暗号化されたにシリアル化し cookie ます。The middleware serializes a user principal into an encrypted cookie. 後続の要求では、ミドルウェアはを検証し、 cookie プリンシパルを再作成して、そのプリンシパルをHttpContextUserプロパティに割り当てます。On subsequent requests, the middleware validates the cookie, recreates the principal, and assigns the principal to the User property of HttpContext.

トークンベースの認証Token-based authentication

ユーザーが認証されると、トークンが発行されます (偽造防止トークンではありません)。When a user is authenticated, they're issued a token (not an antiforgery token). このトークンには、 要求 の形式でユーザー情報が含まれているか、アプリがアプリで保持されているユーザー状態を示す参照トークンが含まれています。The token contains user information in the form of claims or a reference token that points the app to user state maintained in the app. ユーザーが認証を必要とするリソースにアクセスしようとすると、トークンは、ベアラートークンの形式で追加の authorization ヘッダーを使用してアプリに送信されます。When a user attempts to access a resource requiring authentication, the token is sent to the app with an additional authorization header in form of Bearer token. これにより、アプリはステートレスになります。This makes the app stateless. 後続の各要求では、サーバー側の検証要求でトークンが渡されます。In each subsequent request, the token is passed in the request for server-side validation. このトークンは 暗号化さ れていません。これは エンコード されます。This token isn't encrypted ; it's encoded . サーバーでは、トークンをデコードして情報にアクセスします。On the server, the token is decoded to access its information. 後続の要求でトークンを送信するには、ブラウザーのローカルストレージにトークンを格納します。To send the token on subsequent requests, store the token in the browser's local storage. トークンがブラウザーのローカルストレージに格納されている場合、CSRF の脆弱性について心配しないでください。Don't be concerned about CSRF vulnerability if the token is stored in the browser's local storage. CSRF は、トークンがに格納されている場合に問題になり cookie ます。CSRF is a concern when the token is stored in a cookie. 詳細については、GitHub の issue SPA のコードサンプルを cookie 参照してください。For more information, see the GitHub issue SPA code sample adds two cookies.

1つのドメインでホストされている複数のアプリMultiple apps hosted at one domain

共有ホスティング環境は、セッションハイジャック、ログイン CSRF、およびその他の攻撃に対して脆弱です。Shared hosting environments are vulnerable to session hijacking, login CSRF, and other attacks.

example1.contoso.netexample2.contoso.net は異なるホストですが、ドメイン内のホスト間には暗黙的な信頼関係があり *.contoso.net ます。Although example1.contoso.net and example2.contoso.net are different hosts, there's an implicit trust relationship between hosts under the *.contoso.net domain. この暗黙的な信頼関係により、信頼できない可能性のあるホストが互いのに影響を与えることがあり cookie ます (AJAX 要求を管理する同じオリジンポリシーは必ずしも HTTP s に適用されるわけではありません cookie )。This implicit trust relationship allows potentially untrusted hosts to affect each other's cookies (the same-origin policies that govern AJAX requests don't necessarily apply to HTTP cookies).

同じドメインでホストされているアプリ間で信頼されたを利用する攻撃は cookie 、ドメインを共有しないことで回避できます。Attacks that exploit trusted cookies between apps hosted on the same domain can be prevented by not sharing domains. 各アプリが独自のドメインでホストされている場合、 cookie 悪用に対する暗黙の信頼関係はありません。When each app is hosted on its own domain, there is no implicit cookie trust relationship to exploit.

ASP.NET Core 偽造防止の構成ASP.NET Core antiforgery configuration

警告

ASP.NET Core は ASP.NET Core データ保護を使用してアンチ偽造を実装します。ASP.NET Core implements antiforgery using ASP.NET Core Data Protection. データ保護スタックは、サーバーファームで動作するように構成されている必要があります。The data protection stack must be configured to work in a server farm. 詳細については、「 データ保護の構成 」を参照してください。See Configuring data protection for more information.

次のいずれかの Api がで呼び出されると、アンチ偽造ミドルウェアが 依存関係の注入 コンテナーに追加され Startup.ConfigureServices ます。Antiforgery middleware is added to the Dependency injection container when one of the following APIs is called in Startup.ConfigureServices:

が呼び出されると、アンチ偽造ミドルウェアが依存関係挿入コンテナーに追加されます。 AddMvcStartup.ConfigureServicesAntiforgery middleware is added to the Dependency injection container when AddMvc is called in Startup.ConfigureServices

ASP.NET Core 2.0 以降では、 Formtaghelper は、アンチ偽造トークンを HTML フォーム要素に挿入します。In ASP.NET Core 2.0 or later, the FormTagHelper injects antiforgery tokens into HTML form elements. ファイル内の次のマークアップは、 Razor アンチ偽造トークンを自動的に生成します。The following markup in a Razor file automatically generates antiforgery tokens:

<form method="post">
    ...
</form>

同様に、フォームのメソッドが GET でない場合、 Ihtmlhelper. BeginForm は既定で偽造防止トークンを生成します。Similarly, IHtmlHelper.BeginForm generates antiforgery tokens by default if the form's method isn't GET.

HTML フォーム要素のアンチ偽造トークンの自動生成は、タグに <form> 属性が含まれて method="post" おり、次のいずれかが当てはまる場合に発生します。The automatic generation of antiforgery tokens for HTML form elements happens when the <form> tag contains the method="post" attribute and either of the following are true:

  • Action 属性が空です ( action="" )。The action attribute is empty (action="").
  • Action 属性が指定されていません ( <form method="post"> )。The action attribute isn't supplied (<form method="post">).

HTML フォーム要素のアンチ偽造トークンの自動生成は無効にすることができます。Automatic generation of antiforgery tokens for HTML form elements can be disabled:

  • 属性を使用してアンチ偽造トークンを明示的に無効にし asp-antiforgery ます。Explicitly disable antiforgery tokens with the asp-antiforgery attribute:

    <form method="post" asp-antiforgery="false">
        ...
    </form>
    
  • Form 要素は、タグヘルパー ! オプトアウトシンボルを使用してタグヘルパーをオプトアウトします。The form element is opted-out of Tag Helpers by using the Tag Helper ! opt-out symbol:

    <!form method="post">
        ...
    </!form>
    
  • ビューからを削除し FormTagHelper ます。Remove the FormTagHelper from the view. ビュー FormTagHelper に次のディレクティブを追加することで、ビューからを削除でき Razor ます。The FormTagHelper can be removed from a view by adding the following directive to the Razor view:

    @removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
    

注意

Razor ページは XSRF/csrf から自動的に保護されます。Razor Pages are automatically protected from XSRF/CSRF. 詳細については、「 XSRF/CSRF と Razor Pages」を参照してください。For more information, see XSRF/CSRF and Razor Pages.

CSRF 攻撃を防ぐための最も一般的な方法は、 シンクロナイザートークンパターン (STP) を使用することです。The most common approach to defending against CSRF attacks is to use the Synchronizer Token Pattern (STP). STP は、ユーザーがフォームデータを使用してページを要求したときに使用されます。STP is used when the user requests a page with form data:

  1. サーバーは、現在のユーザーの id に関連付けられているトークンをクライアントに送信します。The server sends a token associated with the current user's identity to the client.
  2. クライアントは、トークンを検証のためにサーバーに送り返します。The client sends back the token to the server for verification.
  3. サーバーが、認証されたユーザーの id と一致しないトークンを受け取った場合、要求は拒否されます。If the server receives a token that doesn't match the authenticated user's identity, the request is rejected.

トークンは一意で、予測できません。The token is unique and unpredictable. このトークンは、一連の要求を適切にシーケンス処理するためにも使用できます (たとえば、ページ 1 > ページ 2 > ページ 3)。The token can also be used to ensure proper sequencing of a series of requests (for example, ensuring the request sequence of: page 1 > page 2 > page 3). ASP.NET Core MVC およびページテンプレートのすべてのフォームで、 Razor 偽造防止トークンが生成されます。All of the forms in ASP.NET Core MVC and Razor Pages templates generate antiforgery tokens. 次の2つのビュー例では、偽造偽造トークンが生成されます。The following pair of view examples generate antiforgery tokens:

<form asp-controller="Manage" asp-action="ChangePassword" method="post">
    ...
</form>

@using (Html.BeginForm("ChangePassword", "Manage"))
{
    ...
}

<form>タグヘルパーと HTML ヘルパーを使用せずに、次のように、アンチ偽造トークンを要素に明示的に追加し @Html.AntiForgeryToken ます。Explicitly add an antiforgery token to a <form> element without using Tag Helpers with the HTML helper @Html.AntiForgeryToken:

<form action="/" method="post">
    @Html.AntiForgeryToken()
</form>

これらの各ケースでは、次のような非表示のフォームフィールドが ASP.NET Core によって追加されます。In each of the preceding cases, ASP.NET Core adds a hidden form field similar to the following:

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">

ASP.NET Core には、偽造防止トークンを操作するための3つの フィルター が含まれています。ASP.NET Core includes three filters for working with antiforgery tokens:

偽造防止オプションAntiforgery options

次の方法で 偽造防止オプション をカスタマイズし Startup.ConfigureServices ます。Customize antiforgery options in Startup.ConfigureServices:

services.AddAntiforgery(options => 
{
    // Set Cookie properties using CookieBuilder properties†.
    options.FormFieldName = "AntiforgeryFieldname";
    options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
    options.SuppressXFrameOptionsHeader = false;
});

Cookie Cookie ビルダークラスのプロパティを使用して、アンチ偽造プロパティを設定します。†Set the antiforgery Cookie properties using the properties of the CookieBuilder class.

オプションOption [説明]Description
Cookie アンチ偽造を作成するために使用する設定を決定し cookie ます。Determines the settings used to create the antiforgery cookies.
FormFieldNameFormFieldName アンチ偽造システムがビューで偽造防止トークンをレンダリングするために使用する非表示フォームフィールドの名前。The name of the hidden form field used by the antiforgery system to render antiforgery tokens in views.
HeaderNameHeaderName アンチ偽造システムによって使用されるヘッダーの名前。The name of the header used by the antiforgery system. の場合 null 、システムはフォームデータのみを考慮します。If null, the system considers only form data.
SuppressXFrameOptionsHeaderSuppressXFrameOptionsHeader ヘッダーの生成を抑制するかどうかを指定し X-Frame-Options ます。Specifies whether to suppress generation of the X-Frame-Options header. 既定では、ヘッダーは値 "SAMEORIGIN" を使用して生成されます。By default, the header is generated with a value of "SAMEORIGIN". 既定値は false です。Defaults to false.
services.AddAntiforgery(options => 
{
    options.CookieDomain = "contoso.com";
    options.CookieName = "X-CSRF-TOKEN-COOKIENAME";
    options.CookiePath = "Path";
    options.FormFieldName = "AntiforgeryFieldname";
    options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
    options.RequireSsl = false;
    options.SuppressXFrameOptionsHeader = false;
});
オプションOption [説明]Description
Cookie アンチ偽造を作成するために使用する設定を決定し cookie ます。Determines the settings used to create the antiforgery cookies.
CookieDomainCookieDomain のドメイン cookie 。The domain of the cookie. 既定値は null です。Defaults to null. このプロパティは互換性のために残されていますが、今後のバージョンでは削除される予定です。This property is obsolete and will be removed in a future version. 別の方法をお勧めし Cookie ます。領域.The recommended alternative is Cookie.Domain.
CookieNameCookieName cookie の名前。The name of the cookie. 設定しない場合、システムは 既定の Cookie プレフィックス ("を使用して、一意の名前を生成します。AspNetCore。 ")。If not set, the system generates a unique name beginning with the DefaultCookiePrefix (".AspNetCore.Antiforgery."). このプロパティは互換性のために残されていますが、今後のバージョンでは削除される予定です。This property is obsolete and will be removed in a future version. 別の方法をお勧めし Cookie ます。指定.The recommended alternative is Cookie.Name.
Cookie道CookiePath に設定されたパス cookie 。The path set on the cookie. このプロパティは互換性のために残されていますが、今後のバージョンでは削除される予定です。This property is obsolete and will be removed in a future version. 別の方法をお勧めし Cookie ます。道.The recommended alternative is Cookie.Path.
FormFieldNameFormFieldName アンチ偽造システムがビューで偽造防止トークンをレンダリングするために使用する非表示フォームフィールドの名前。The name of the hidden form field used by the antiforgery system to render antiforgery tokens in views.
HeaderNameHeaderName アンチ偽造システムによって使用されるヘッダーの名前。The name of the header used by the antiforgery system. の場合 null 、システムはフォームデータのみを考慮します。If null, the system considers only form data.
RequireSslRequireSsl 偽造防止システムによって HTTPS が要求されるかどうかを指定します。Specifies whether HTTPS is required by the antiforgery system. trueの場合、HTTPS 以外の要求は失敗します。If true, non-HTTPS requests fail. 既定値は false です。Defaults to false. このプロパティは互換性のために残されていますが、今後のバージョンでは削除される予定です。This property is obsolete and will be removed in a future version. 別の方法として、を設定することをお勧めし Cookie ます。SecurePolicy。The recommended alternative is to set Cookie.SecurePolicy.
SuppressXFrameOptionsHeaderSuppressXFrameOptionsHeader ヘッダーの生成を抑制するかどうかを指定し X-Frame-Options ます。Specifies whether to suppress generation of the X-Frame-Options header. 既定では、ヘッダーは値 "SAMEORIGIN" を使用して生成されます。By default, the header is generated with a value of "SAMEORIGIN". 既定値は false です。Defaults to false.

詳細については、「 Cookie authenticationoptions」を参照してください。For more information, see CookieAuthenticationOptions.

偽造防止機能の構成 (Iアンチ偽造)Configure antiforgery features with IAntiforgery

Iアンチ偽造 は、偽造防止機能を構成するための API を提供します。IAntiforgery provides the API to configure antiforgery features. IAntiforgeryConfigure 、クラスのメソッドで要求でき Startup ます。IAntiforgery can be requested in the Configure method of the Startup class. 次の例では、アプリのホームページからミドルウェアを使用して、アンチ偽造トークンを生成し、として応答に送信し cookie ます (このトピックで後述する既定の角度の名前付け規則を使用します)。The following example uses middleware from the app's home page to generate an antiforgery token and send it in the response as a cookie (using the default Angular naming convention described later in this topic):

public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
    app.Use(next => context =>
    {
        string path = context.Request.Path.Value;

        if (
            string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
            string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
        {
            // The request token can be sent as a JavaScript-readable cookie, 
            // and Angular uses it by default.
            var tokens = antiforgery.GetAndStoreTokens(context);
            context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, 
                new CookieOptions() { HttpOnly = false });
        }

        return next(context);
    });
}

偽造防止の検証を必要とするRequire antiforgery validation

Validateアンチ Forgerytoken は、個々のアクション、コントローラー、またはグローバルに適用できるアクションフィルターです。ValidateAntiForgeryToken is an action filter that can be applied to an individual action, a controller, or globally. このフィルターが適用されているアクションに対して行われた要求は、要求に有効な偽造偽造トークンが含まれていない限り、ブロックされます。Requests made to actions that have this filter applied are blocked unless the request includes a valid antiforgery token.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
    ManageMessageId? message = ManageMessageId.Error;
    var user = await GetCurrentUserAsync();

    if (user != null)
    {
        var result = 
            await _userManager.RemoveLoginAsync(
                user, account.LoginProvider, account.ProviderKey);

        if (result.Succeeded)
        {
            await _signInManager.SignInAsync(user, isPersistent: false);
            message = ManageMessageId.RemoveLoginSuccess;
        }
    }

    return RedirectToAction(nameof(ManageLogins), new { Message = message });
}

属性には、 ValidateAntiForgeryToken HTTP GET 要求を含む、マークするアクションメソッドへの要求にトークンが必要です。The ValidateAntiForgeryToken attribute requires a token for requests to the action methods it marks, including HTTP GET requests. ValidateAntiForgeryToken属性がアプリのコントローラー全体に適用される場合は、属性でオーバーライドでき IgnoreAntiforgeryToken ます。If the ValidateAntiForgeryToken attribute is applied across the app's controllers, it can be overridden with the IgnoreAntiforgeryToken attribute.

注意

ASP.NET Core は、要求を自動的に取得するための偽造防止トークンの追加をサポートしていません。ASP.NET Core doesn't support adding antiforgery tokens to GET requests automatically.

安全でない HTTP メソッドに対してのみ偽造防止トークンを自動的に検証するAutomatically validate antiforgery tokens for unsafe HTTP methods only

ASP.NET Core アプリは、安全な HTTP メソッド (GET、HEAD、OPTIONS、および TRACE) に対して偽造防止トークンを生成しません。ASP.NET Core apps don't generate antiforgery tokens for safe HTTP methods (GET, HEAD, OPTIONS, and TRACE). 属性を広範に適用して属性でオーバーライドするのではなく ValidateAntiForgeryToken IgnoreAntiforgeryTokenAutovalidateアンチ Forgerytoken 属性を使用できます。Instead of broadly applying the ValidateAntiForgeryToken attribute and then overriding it with IgnoreAntiforgeryToken attributes, the AutoValidateAntiforgeryToken attribute can be used. この属性は、属性と同じように動作し ValidateAntiForgeryToken ますが、次の HTTP メソッドを使用して行われた要求に対してトークンを必要としない点が異なります。This attribute works identically to the ValidateAntiForgeryToken attribute, except that it doesn't require tokens for requests made using the following HTTP methods:

  • GETGET
  • HEADHEAD
  • OPTIONSOPTIONS
  • TRACETRACE

非 API のシナリオでは、広範なを使用することをお勧め AutoValidateAntiforgeryToken します。We recommend use of AutoValidateAntiforgeryToken broadly for non-API scenarios. これにより、POST アクションが既定で保護されるようになります。This ensures POST actions are protected by default. 代替手段は、 ValidateAntiForgeryToken が個々のアクションメソッドに適用されない限り、既定で偽造防止トークンを無視することです。The alternative is to ignore antiforgery tokens by default, unless ValidateAntiForgeryToken is applied to individual action methods. このシナリオでは、POST アクションメソッドが誤って保護されないままになり、アプリが CSRF 攻撃に対して脆弱になる可能性が高くなります。It's more likely in this scenario for a POST action method to be left unprotected by mistake, leaving the app vulnerable to CSRF attacks. すべての投稿は、アンチ偽造トークンを送信する必要があります。All POSTs should send the antiforgery token.

Api には、トークンの一部を送信するための自動メカニズムがありません cookie 。APIs don't have an automatic mechanism for sending the non-cookie part of the token. 実装は、クライアントコードの実装によって異なる場合があります。The implementation probably depends on the client code implementation. いくつかの例を次に示します。Some examples are shown below:

クラスレベルの例:Class-level example:

[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{

グローバルな例:Global example:

サーヴィス.AddMvc (オプション => オプション。Filters。 Add (新しい Autovalidateアンチ Forgerytokenattribute ());services.AddMvc(options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));

services.AddControllersWithViews(options =>
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));

グローバルまたはコントローラーのアンチ偽造属性を上書きするOverride global or controller antiforgery attributes

Ignoreアンチ Forgerytokenフィルターは、特定のアクション (またはコントローラー) に対して偽造防止トークンが不要になるようにするために使用されます。The IgnoreAntiforgeryToken filter is used to eliminate the need for an antiforgery token for a given action (or controller). このフィルターを適用すると ValidateAntiForgeryTokenAutoValidateAntiforgeryToken より高いレベルで指定されたフィルター (グローバルまたはコントローラー上) が上書きされます。When applied, this filter overrides ValidateAntiForgeryToken and AutoValidateAntiforgeryToken filters specified at a higher level (globally or on a controller).

[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
    [HttpPost]
    [IgnoreAntiforgeryToken]
    public async Task<IActionResult> DoSomethingSafe(SomeViewModel model)
    {
        // no antiforgery token required
    }
}

認証後のトークンの更新Refresh tokens after authentication

ユーザーを認証した後で、ユーザーをビューページまたはページページにリダイレクトすることによって、トークンを更新する必要があり Razor ます。Tokens should be refreshed after the user is authenticated by redirecting the user to a view or Razor Pages page.

JavaScript、AJAX、および SPAsJavaScript, AJAX, and SPAs

従来の HTML ベースのアプリでは、非表示のフォームフィールドを使用して、偽造防止トークンがサーバーに渡されます。In traditional HTML-based apps, antiforgery tokens are passed to the server using hidden form fields. 最新の JavaScript ベースのアプリと SPAs では、多くの要求がプログラムによって行われます。In modern JavaScript-based apps and SPAs, many requests are made programmatically. これらの AJAX 要求では、他の手法 (要求ヘッダー cookie 、s など) を使用してトークンを送信できます。These AJAX requests may use other techniques (such as request headers or cookies) to send the token.

cookieが認証トークンの格納に使用され、サーバーで API 要求を認証するために、CSRF が発生する可能性があります。If cookies are used to store authentication tokens and to authenticate API requests on the server, CSRF is a potential problem. ローカルストレージを使用してトークンを格納している場合は、ローカルストレージからの値がすべての要求でサーバーに自動的に送信されないため、CSRF 脆弱性が軽減される可能性があります。If local storage is used to store the token, CSRF vulnerability might be mitigated because values from local storage aren't sent automatically to the server with every request. したがって、ローカルストレージを使用して、クライアントにアンチ偽造トークンを格納し、要求ヘッダーとしてトークンを送信することをお勧めします。Thus, using local storage to store the antiforgery token on the client and sending the token as a request header is a recommended approach.

JavaScriptJavaScript

ビューで JavaScript を使用すると、ビュー内からサービスを使用してトークンを作成できます。Using JavaScript with views, the token can be created using a service from within the view. ビューに AspNetCore の偽造 サービスを挿入し、 Getandstoretokensを呼び出します。Inject the Microsoft.AspNetCore.Antiforgery.IAntiforgery service into the view and call GetAndStoreTokens:

@{
    ViewData["Title"] = "AJAX Demo";
}
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}

<input type="hidden" id="RequestVerificationToken" 
       name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">

<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<div class="row">
    <p><input type="button" id="antiforgery" value="Antiforgery"></p>
    <script>
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (xhttp.readyState == XMLHttpRequest.DONE) {
                if (xhttp.status == 200) {
                    alert(xhttp.responseText);
                } else {
                    alert('There was an error processing the AJAX request.');
                }
            }
        };

        document.addEventListener('DOMContentLoaded', function() {
            document.getElementById("antiforgery").onclick = function () {
                xhttp.open('POST', '@Url.Action("Antiforgery", "Home")', true);
                xhttp.setRequestHeader("RequestVerificationToken", 
                    document.getElementById('RequestVerificationToken').value);
                xhttp.send();
            }
        });
    </script>
</div>

この方法を使用すると、サーバーからのの設定やクライアントからの読み取りを直接処理する必要がなくなり cookie ます。This approach eliminates the need to deal directly with setting cookies from the server or reading them from the client.

前の例では、JavaScript を使用して、AJAX POST ヘッダーの隠しフィールド値を読み取ります。The preceding example uses JavaScript to read the hidden field value for the AJAX POST header.

また、JavaScript は、のトークンにアクセス cookie し、そのコンテンツを使用して、 cookie トークンの値を持つヘッダーを作成することもできます。JavaScript can also access tokens in cookies and use the cookie's contents to create a header with the token's value.

context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken, 
    new Microsoft.AspNetCore.Http.CookieOptions { HttpOnly = false });

スクリプトがというヘッダー内のトークンを送信するように要求した X-CSRF-TOKEN 場合、そのヘッダーを検索するようにアンチ偽造サービスを構成し X-CSRF-TOKEN ます。Assuming the script requests to send the token in a header called X-CSRF-TOKEN, configure the antiforgery service to look for the X-CSRF-TOKEN header:

services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");

次の例では、JavaScript を使用して、適切なヘッダーを含む AJAX 要求を作成します。The following example uses JavaScript to make an AJAX request with the appropriate header:

function getCookie(cname) {
    var name = cname + "=";
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(';');
    for(var i = 0; i <ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

var csrfToken = getCookie("CSRF-TOKEN");

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (xhttp.readyState == XMLHttpRequest.DONE) {
        if (xhttp.status == 200) {
            alert(xhttp.responseText);
        } else {
            alert('There was an error processing the AJAX request.');
        }
    }
};
xhttp.open('POST', '/api/password/changepassword', true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("X-CSRF-TOKEN", csrfToken);
xhttp.send(JSON.stringify({ "newPassword": "ReallySecurePassword999$$$" }));

AngularJSAngularJS

AngularJS は、規約を使用して CSRF に対処します。AngularJS uses a convention to address CSRF. サーバーがという名前のを送信した場合 cookie XSRF-TOKEN 、AngularJS サービスは、 $http cookie サーバーに要求を送信するときに、ヘッダーに値を追加します。If the server sends a cookie with the name XSRF-TOKEN, the AngularJS $http service adds the cookie value to a header when it sends a request to the server. このプロセスは自動的に実行されます。This process is automatic. ヘッダーは、クライアントで明示的に設定する必要はありません。The header doesn't need to be set in the client explicitly. ヘッダー名が X-XSRF-TOKEN です。The header name is X-XSRF-TOKEN. サーバーは、このヘッダーを検出し、その内容を検証する必要があります。The server should detect this header and validate its contents.

アプリケーションの起動時に、ASP.NET Core API がこの規則を使用するようにするには、次の操作を行います。For ASP.NET Core API to work with this convention in your application startup:

  • という名前のでトークンを提供するようにアプリを構成 cookie XSRF-TOKEN します。Configure your app to provide a token in a cookie called XSRF-TOKEN.
  • という名前のヘッダーを検索するようにアンチ偽造サービスを構成 X-XSRF-TOKEN します。Configure the antiforgery service to look for a header named X-XSRF-TOKEN.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
    app.Use(next => context =>
    {
        string path = context.Request.Path.Value;

        if (
            string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
            string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
        {
            // The request token can be sent as a JavaScript-readable cookie, 
            // and Angular uses it by default.
            var tokens = antiforgery.GetAndStoreTokens(context);
            context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, 
                new CookieOptions() { HttpOnly = false });
        }

        return next(context);
    });
}

public void ConfigureServices(IServiceCollection services)
{
    // Angular's default header name for sending the XSRF token.
    services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
}

サンプル コードを表示またはダウンロードします (ダウンロード方法)。View or download sample code (how to download)

アンチ偽造の延長Extend antiforgery

Iアンチ Forgeryadditionaldataprovider型を使用すると、開発者は各トークンの追加データをラウンドトリップさせることで、csrf システムの動作を拡張できます。The IAntiForgeryAdditionalDataProvider type allows developers to extend the behavior of the anti-CSRF system by round-tripping additional data in each token. Getadditionaldataメソッドは、フィールドトークンが生成されるたびに呼び出され、戻り値は生成されたトークン内に埋め込まれます。The GetAdditionalData method is called each time a field token is generated, and the return value is embedded within the generated token. 実装者は、タイムスタンプ、nonce、またはその他の値を返し、 Validateadditionaldata を呼び出して、トークンが検証されたときにこのデータを検証することができます。An implementer could return a timestamp, a nonce, or any other value and then call ValidateAdditionalData to validate this data when the token is validated. クライアントのユーザー名は、生成されたトークンに既に埋め込まれているため、この情報を含める必要はありません。The client's username is already embedded in the generated tokens, so there's no need to include this information. トークンに追加データが含まれていても構成されていない場合 IAntiForgeryAdditionalDataProvider 、補足データは検証されません。If a token includes supplemental data but no IAntiForgeryAdditionalDataProvider is configured, the supplemental data isn't validated.

その他の資料Additional resources