Tuesday, October 23, 2007

The Ajax Control Toolkit NoBot control and session state

You need to prevent hackers using robots to run dictionaries of user names and passwords against your login pages. The most common way to achieve that is the use of Captchas ("Completely Automated Public Turing test to tell Computers and Humans Apart"), which display an image with a code which you need to type in a text box. Captchas are often difficult to read and push away genuine users with disabilities. More elaborated Captchas include sound but they are not mainstream.

The NoBot control in the Microsoft Ajax Control Toolkit can be used for any type of request and in particular to protect the sign in function of a login page:

  1. It makes sure too many requests (to sign in) are not issued from the same IP address;
  2. It provides an automated challenge response mechanism to ensure the request (to sign in) is issued by the (login) page;
  3. It enforces a delay between the time the (login) page is displayed and the request (to sign in) is issued.

The benefit of the NoBot control is that this is transparent to the user, contrary to Captchas.

You implement the NoBot control on your ASP.NET page as follows:

<ajaxToolkit:NoBot
ID="PageNoBot"
runat="server"
OnGenerateChallengeAndResponse="PageNoBot_GenerateChallengeAndResponse"
ResponseMinimumDelaySeconds="3"
CutoffMaximumInstances="5"
CutoffWindowSeconds="60"
/>

You implement the OnGenerateChallengeAndResponse event handler in code as follows:

protected
void PageNoBot_GenerateChallengeAndResponse(object sender, AjaxControlToolkit.NoBotEventArgs e)

{


Random r = new
Random();


int iFirst = r.Next(100);


int iSecond = r.Next(100);

e.ChallengeScript = String.Format("eval('{0}+{1}')", iFirst, iSecond);

e.RequiredResponse = Convert.ToString(iFirst + iSecond);

}

Then the documentation tells you to implement the click event handler of the sign in button as follows:

if (!PageNoBot.IsValid()) {


//Display a message that a robot has been detected and the request cannot be processed

}

else {


//Process the postback event

}

On most sites users are redirected to the login page when sessions time out. Because the NoBot control stores the calculation in session state and session state is reset in this case, the calculation challenge response would fail teh next time the user logs in unless he/she refreshes the page.

The following solves the problem from the user perspective, but it also opens the door to hackers:

if ((!Page.Session.IsNewSession) && (!PageNoBot.IsValid()))

Apart from redesigning the NoBot control, not to use session state but to use the context cache instead, I have not found a really good solution to solve this issue.