J'ai créé une application Web Forms ASP.Net à l'aide de Visual Studio 2013 et j'utilise .NET Framework 4.5. Je veux m'assurer que mon site est sécurisé contre la contrefaçon de demande intersite (CSRF), j'ai trouvé de nombreux articles sur la façon dont cette fonctionnalité est implémentée sur les applications MVC, mais très peu parlent de formulaires Web. On cette question StackOverflow un commentaire déclare que
"C'est une vieille question, mais le dernier modèle ASP.NET de Visual Studio 2012 pour les formulaires Web inclut du code anti-CSRF intégré dans la page maître. Si vous n'avez pas les modèles, voici le code qu'il génère: ..."
Ma page maître ne contient pas le code mentionné dans cette réponse. Est-il vraiment inclus dans les nouvelles applications? Sinon, quelle est la meilleure façon de l'ajouter?
ViewStateUserKey & Double Submit Cookie
À partir de Visual Studio 2012, Microsoft a ajouté une protection CSRF intégrée aux nouveaux projets d'application de formulaires Web. Pour utiliser ce code, ajoutez une nouvelle application ASP .NET Web Forms à votre solution et affichez le code Site.Master derrière la page. Cette solution appliquera la protection CSRF à toutes les pages de contenu héritant de la Page Site.Master.
Les conditions suivantes doivent être remplies pour que cette solution fonctionne:
Tous les formulaires Web apportant des modifications aux données doivent utiliser la page Site.Master. Toutes les demandes de modification de données doivent utiliser ViewState. Le site Web doit être exempt de toutes les vulnérabilités Cross-Site Scripting (XSS). Découvrez comment corriger les scripts intersites (XSS) à l'aide de la bibliothèque de protection Web Microsoft .Net pour plus de détails.
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.");
}
}
}
}
Vous pouvez essayer ce qui suit. Dans le formulaire Web, ajoutez:
<%= System.Web.Helpers.AntiForgery.GetHtml() %>
Cela ajoutera un champ caché et un cookie. Donc, si vous remplissez certaines données du formulaire et les renvoyez sur le serveur, vous avez besoin d'une simple vérification:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
AntiForgery.Validate();
}
AntiForgery.Validate();
lève une exception si la vérification anti XSFR échoue.
Lorsque vous créez un nouveau projet "Application de formulaire Web" dans VS 2013, le site.master.cs inclura automatiquement le code XSRF/CSRF dans le Page_Init
section de la classe. Si vous n'obtenez toujours pas le code généré, vous pouvez manuellement Copy
+ Paste
le code. Si vous utilisez C #, utilisez ce qui suit: -
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.");
}
}
}