Visual Studio 2013を使用してASP.Net Webフォームアプリケーションを作成し、.NET Framework 4.5を使用しています。私のサイトがクロスサイトリクエストフォージェリ(CSRF)から保護されていることを確認したいのですが、MVCアプリでこの機能がどのように実装されているかについて多くの記事を見つけましたが、Webフォームについてはほとんどありません。オン このStackOverflowの質問 1つのコメントは、
「これは古い質問ですが、Webフォーム用の最新のVisual Studio 2012 ASP.NETテンプレートには、マスターページに焼き付けられたanti-CSRFコードが含まれています。テンプレートがない場合、生成されるコードは次のとおりです。..」
私のマスターページには、その回答に記載されているコードは含まれていません。それは本当に新しいアプリケーションに含まれていますか?そうでない場合、それを追加する最良の方法は何ですか?
ViewStateUserKeyと二重送信Cookie
Visual Studio 2012以降、Microsoftは組み込みのCSRF保護を新しいWebフォームアプリケーションプロジェクトに追加しました。このコードを利用するには、新しいASP .NET Webフォームアプリケーションをソリューションに追加し、Site.Masterコードビハインドページを表示します。このソリューションは、 Site.Masterページ。
このソリューションが機能するには、次の要件を満たす必要があります。
データを変更するすべてのWebフォームは、Site.Masterページを使用する必要があります。データ変更を行うすべての要求は、ViewStateを使用する必要があります。 Webサイトには、すべてのクロスサイトスクリプティング(XSS)の脆弱性が存在しない必要があります。詳細については、Microsoft .Net Web Protection Libraryを使用してクロスサイトスクリプティング(XSS)を修正する方法を参照してください。
public partial class SiteMaster : MasterPage
{
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
//First, check for the existence of the Anti-XSS cookie
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
//If the CSRF cookie is found, parse the token from the cookie.
//Then, set the global page variable and view state user
//key. The global variable will be used to validate that it matches
//in the view state form field in the Page.PreLoad method.
if (requestCookie != null
&& Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
//Set the global token variable so the cookie value can be
//validated against the value in the view state form field in
//the Page.PreLoad method.
_antiXsrfTokenValue = requestCookie.Value;
//Set the view state user key, which will be validated by the
//framework during each request
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
//If the CSRF cookie is not found, then this is a new session.
else
{
//Generate a new Anti-XSRF token
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
//Set the view state user key, which will be validated by the
//framework during each request
Page.ViewStateUserKey = _antiXsrfTokenValue;
//Create the non-persistent CSRF cookie
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
//Set the HttpOnly property to prevent the cookie from
//being accessed by client side script
HttpOnly = true,
//Add the Anti-XSRF token to the cookie value
Value = _antiXsrfTokenValue
};
//If we are using SSL, the cookie should be set to secure to
//prevent it from being sent over HTTP connections
if (FormsAuthentication.RequireSSL &&
Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
//Add the CSRF cookie to the response
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
//During the initial page load, add the Anti-XSRF token and user
//name to the ViewState
if (!IsPostBack)
{
//Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
//If a user name is assigned, set the user name
ViewState[AntiXsrfUserNameKey] =
Context.User.Identity.Name ?? String.Empty;
}
//During all subsequent post backs to the page, the token value from
//the cookie should be validated against the token in the view state
//form field. Additionally user name should be compared to the
//authenticated users name
else
{
//Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] !=
(Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of " +
"Anti-XSRF token failed.");
}
}
}
}
以下を試すことができます。 Webフォームに以下を追加します。
_<%= System.Web.Helpers.AntiForgery.GetHtml() %>
_
これにより、非表示フィールドとCookieが追加されます。したがって、フォームデータを入力してサーバーにポストバックする場合、簡単なチェックが必要です。
_protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
AntiForgery.Validate();
}
_
AntiForgery.Validate();
は、アンチXSFRチェックが失敗した場合に例外をスローします。
VS 2013で新しい「Webフォームアプリケーション」プロジェクトを作成すると、site.master.csは自動的にXSRF/CSRFコードをPage_Init
クラスのセクション。それでも生成されたコードを取得できない場合は、手動でCopy
+ Paste
コードを使用できます。 C#を使用している場合は、以下を使用してください。
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
// The code below helps to protect against XSRF attacks
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
// Use the Anti-XSRF token from the cookie
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
else
{
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
HttpOnly = true,
Value = _antiXsrfTokenValue
};
if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
}
else
{
// Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
}
}
}