web-dev-qa-db-ja.com

ASP.NET MVC 4でデフォルトでCSRFから保護するにはどうすればよいですか?

ASP.NET MVC 4フォームがデフォルトでCSRFから保護されていることを確認する方法はありますか?

たとえば、AntiForgeryTokenを自動的にビューとコントローラーアクションの両方のすべてのフォームに適用する方法はありますか?

この質問の背景: ASP.NET MVCのAntiForgeryToken()ヘルパーを使用してクロスサイトリクエストフォージェリ(CSRF)を防止する および クロスサイトリクエストフォージェリ攻撃の構造

22

osoviejoの優れた回答に追加するために、最近の CSRFに関するブログ投稿 からの以下の手順を、Philのブログの情報と1つの包括的な回答にまとめました。

ASP.NET/MVCは、このためのメカニズムを提供します。グローバルFilterProvidersオブジェクトのフィルターのコレクションに追加できます。これにより、一部のコントローラーをターゲットにして、他のコントローラーをターゲットにせず、必要なセキュリティ機能を追加できます。

まず、IFilterProviderを実装する必要があります。以下に、Phil Haackの 条件付きフィルタープロバイダー クラスを示します。このクラスをプロジェクトに追加することから始めます。

public class ConditionalFilterProvider : IFilterProvider
{
    private readonly
      IEnumerable<Func<ControllerContext, ActionDescriptor, object>> _conditions;

    public ConditionalFilterProvider(
      IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions)
    {
        _conditions = conditions;
    }

    public IEnumerable<Filter> GetFilters(
        ControllerContext controllerContext,
        ActionDescriptor actionDescriptor)
    {
        return from condition in _conditions
               select condition(controllerContext, actionDescriptor) into filter
               where filter != null
               select new Filter(filter, FilterScope.Global, null);
    }
}

次に、新しいConditionalFilterProviderをグローバルFilterProvidersコレクションに追加するコードをApplication_Startに追加して、すべてのPOSTコントローラーメソッドがAntiForgeryTokenを必要とすることを確認します。

IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions = 
    new Func<ControllerContext, ActionDescriptor, object>[] {
    // Ensure all POST actions are automatically 
    // decorated with the ValidateAntiForgeryTokenAttribute.

    ( c, a ) => string.Equals( c.HttpContext.Request.HttpMethod, "POST",
    StringComparison.OrdinalIgnoreCase ) ?
    new ValidateAntiForgeryTokenAttribute() : null
};

var provider = new ConditionalFilterProvider(conditions);

// This line adds the filter we created above
FilterProviders.Providers.Add(provider);

上記の2つのコードを実装する場合、MVCアプリケーションはサイトへのeveryPOST)のAntiForgeryTokenを必要とします。 .Phil Haackの CSRFサンプルWebサイト で試してみることができます-保護されると、CSRF攻撃はSystem.Web.Mvc.HttpAntiForgeryExceptionアノテーションを追加せずに[ValidateAntiForgeryToken]をスローします。これにより、 「忘れられたプログラマー」関連の脆弱性のホスト全体。

23
Kyle Hodgson

HttpContext.Request.HttpMethod == "POST"の場合は常に、フィルターValidateAntiForgeryTokenAttribute()が適用されるという条件でフィルタープロバイダーを使用できます。

私は基本的に一般的なアプローチに従いました Phil Haackによって説明されています そして適切な条件を追加しました:

// Ensure all POST actions are automatically decorated with the ValidateAntiForgeryTokenAttribute.
( c, a ) => string.Equals( c.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase ) ?
 new ValidateAntiForgeryTokenAttribute() : null
12
osoviejo

FXCopを使用して2つのコード分析ルールを記述しました。1つはすべてのコントローラーアクションにHttpMethod属性を適用する必要があり、もう1つはHttpPost属性を持つアクションを必要とするものもRequiresAntiForgeryToken属性を持っている必要があります。

これは私たちにとってうまくいきました。ルールを書くのは特に難しいことではありません

2
martin308

これを行う1つの方法は、フォームを作成するASP.NET MVCのT4テンプレートを変更して、このコードを自動的に挿入することです。

<% using(Html.Form("UserProfile", "SubmitUpdate")) { %>
    <%= Html.AntiForgeryToken() %>
    <!-- rest of form goes here -->
<% } %>

そしてもちろん、コントローラーメソッドに対応する属性が必要です。

[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
    // ... etc
}

異常に大きい場合を除いて、この方法でアプリケーションを後付けすることは実際にはそれほど難しくありません。私がMVCで書いた最後のアプリケーションは、おそらく改造するのに数時間かかるでしょう。

1
Robert Harvey