The defense is an anti-forgery token. This is essentially a piece of unguessable data that is placed on your page. When a request is POSTed the server can check to confirm that this piece of data, or token, is there. The token can not be acquired by a malicious page so malicious pages can not make successful requests despite the fact that they can send a valid authorization cookie.
The malicious page can actually request the page with the token on it, but the browser will prevent that page from accessing this cross domain data unless the server indicates that it is allowed.
The Microsoft MVC approach involves storing the request token in the cookie and comparing the cookie value with the POSTed data value. Neither the cookie nor the token in the page can be accessed although the cookie is going to be sent. This is done so that the token does not need to be stored on the server in session making this more scalable.
For the project I am working on I put together a very quick AntiForgeryChecker for the web forms part of our application. To use it you add a HiddenInput field on your page:
<asp:HiddenField ID="antiforgery" runat="server"/>
and then make a call in your page load like:
AntiforgeryChecker.Check(this, antiforgery);
The actual object used is below. It uses session instead of the cookie, because we are already using session.
public static class AntiforgeryChecker
{
public static void Check(Page page, HiddenField antiforgery)
{
if (!page.IsPostBack)
{
Guid antiforgeryToken = Guid.NewGuid();
page.Session["AntiforgeryToken"] = antiforgeryToken;
antiforgery.Value = antiforgeryToken.ToString();
}
else
{
Guid stored = (Guid) page.Session["AntiforgeryToken"];
Guid sent = new Guid(antiforgery.Value);
if (sent != stored)
{
throw new SecurityException("XSRF Attack Detected!");
}
}
}
}
Simple and quick way. Really appreciate.
ReplyDeleteGreat. very simple solution.
ReplyDeleteHi my question is how to use as a common solution for all pages. Suppose I have a project that has 100 .aspx pages and my task to resolve XSS vulnerability on application level. In such case I must not make changes in all pages but should find common firing method where I can implement common solution. any help?
ReplyDeleteI am a little rusty on aspx, but you should be able to use a master page.
ReplyDeleteI have got your point but issue with my web app is I haven't used master page on all pages. I am working on to create dynamic hidden field on all page but since I have different kinds of controls on all pages I am failing to create dynamic control and add to all pages when page load. Couldn't find the solution yet.
ReplyDeleteTry putting in Global.asax on this event:
DeleteApplication_BeginRequest: Fired when an application request is received. It is the first event fired for a request, which is often a page request (URL) that a user enters.
Not sure if works. I hope it helps,
Ricardo
Hi
ReplyDeleteThis is an very short and good
But when i try to call in page load as
Antiforgerychecker.Check(this, antiforgery);
I getting error on first argument "cannot convert from "XXXXX" to "System.web.ui.page"
Can any one help me
This happens because your first argument to check is not a page. Hard to diagnose beyond that, but if you were using MVC this would fail because you would be passing a controller. If you structured your code so that the call was made from a sub object this would also happen. You could try pulling the page from the HttpContext instead of using 'this'. Good luck.
ReplyDeleteThis comment has been removed by the author.
ReplyDelete