ASP.NET MVC 4フォームがデフォルトでCSRFから保護されていることを確認する方法はありますか?
たとえば、AntiForgeryTokenを自動的にビューとコントローラーアクションの両方のすべてのフォームに適用する方法はありますか?
この質問の背景: ASP.NET MVCのAntiForgeryToken()ヘルパーを使用してクロスサイトリクエストフォージェリ(CSRF)を防止する および クロスサイトリクエストフォージェリ攻撃の構造 。
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]
をスローします。これにより、 「忘れられたプログラマー」関連の脆弱性のホスト全体。
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
FXCopを使用して2つのコード分析ルールを記述しました。1つはすべてのコントローラーアクションにHttpMethod属性を適用する必要があり、もう1つはHttpPost属性を持つアクションを必要とするものもRequiresAntiForgeryToken属性を持っている必要があります。
これは私たちにとってうまくいきました。ルールを書くのは特に難しいことではありません
これを行う1つの方法は、フォームを作成するASP.NET MVCのT4テンプレートを変更して、このコードを自動的に挿入することです。
<% using(Html.Form("UserProfile", "SubmitUpdate")) { %>
<%= Html.AntiForgeryToken() %>
<!-- rest of form goes here -->
<% } %>
そしてもちろん、コントローラーメソッドに対応する属性が必要です。
[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
// ... etc
}
異常に大きい場合を除いて、この方法でアプリケーションを後付けすることは実際にはそれほど難しくありません。私がMVCで書いた最後のアプリケーションは、おそらく改造するのに数時間かかるでしょう。