Monday, February 18, 2008

Cross-Site Request Forgery – Also an interesting side problem viewstate MAC failed

Cross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF or XSRF, is a type of malicious exploit of a website whereby unauthorized commands are transmitted from a user that the website trusts. Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser.

There are many things we could possible do to prevent/minimize such attacks. One of my techniques to handle this problem is by requiring a secret, user-specific token in all form submissions; that way the attacker's site can't put the right token in its submissions. I do this by using Session ID as ViewStateUserKey and I will make sure my master base has it covered.

Sample code snippet could look like:



protected void Page_Init(object sender, EventArgs e)

{

Page.ViewStateUserKey = Session.SessionID;

}

The idea was to generate a unique view state key to each session and thus preventing the attacking sites from hijacking the session.

An interesting side problem:

The above technique has been my standard for all my projects. However, one small site threw an error: Validation of viewstate MAC failed. There's a whole lot of discussions, documents and scenarios why this error occurs. Typically this is an error that's common in load balanced environments where the encryption/decryption among servers use different keys. Read my knol about basic check list on load-balancing with IIS. On a side note, never disable ViewState encryption by setting EnableViewStateMac="false"; it's a bad idea.

Coming back to our XSRF, a little investigation showed my error was due to the new session id being generated for every post back. This particular site doesn't use sessoins and Asp.Net being stateless never initializes a session unless being used. In my case, a new session id was being generated every time and leading to the view state key being different for each postback. A simple fix is to make sure to initialize the session. The above code snippet in such case was changed to:



protected void Page_Init(object sender, EventArgs e)

{

Session["NeedThisToInitialize"] = "Yes";

Page.ViewStateUserKey = Session.SessionID;

}

Love coding!

1 comment:

Anonymous said...

Thanks much. This tip saved me a bunch of research time. I had copied over a base page class from another project I did long ago and identified the invalid viewstate MAC problem as the ViewStateUserKey. Would have taken a while to figure out a workaround without your blog entry. Good work!