Developer

Enhance ASP.NET site security with the NoBot control

The NoBot control is a nice addition to the ASP.NET toolkit. It offers basic protection from bots with little code. Find out how you can use this control.

 

CAPTCHA is often used to provide a security checkpoint for Web applications. It helps ensure that an actual user is visiting a site as opposed to automated software or robots. As an alternative, Microsoft provides the NoBot control to prevent certain types of unauthorized access to a Web application. Here's a closer look at the control and how you may use it.

The problem

The proliferation of spam and hackers can cause problems for any Web application. The philosophy behind CAPTCHA and the NoBot control is to keep out unwanted visitors — most notably, restrict visitors to real users at a browser. A great feature of the NoBot control is its invisibility, as the user does not see anything because it works in the background.

The NoBot control

The NoBot control is part of the AJAX Control Toolkit, which is a shared-source collection of controls available via CodePlex. It is available for download. It is built on top of the AJAX Extensions included with ASP.NET 3.5. The controls are easily used once installed on your system. If Visual Studio 2008 is used, the controls will appear in the toolbox under the AJAX Control Toolkit heading. Also, remember it is an AJAX control, so a ScriptManager control must be used on the form as well.

The NoBot control utilizes a few techniques for keeping non-human users from a site. First, you may include a JavaScript calculation to be checked against the postback content. That is, verify that the calculation is in the postback as well - this ensures the actual Web page was accessed. Furthermore, you can enforce a delay between the loading of the form and when it is submitted (postback). Also, you can limit the number of requests that may be submitted by an individual IP address within a certain time window.

Behind the scenes

Adding the control to an ASP.NET Web Form is as simple as dragging and dropping it from the Visual Studio toolbox. The following snippet shows the source code for the control with all relevant properties utilized.

<cc1:NoBot ID="NoBotID" runat="server" Enabled="true"

OnGenerateChallengeAndResponse="PageNoBot_GenerateChallengeAndResponse"

ResponseMinimumDelaySeconds="3"

CutoffMaximumInstances="5"

CutoffWindowSeconds="60" />

The following list provides more information on the properties available with the NoBot control:

  • OnGenerateChallengeAndResponse: An optional property to specify the event handler that allows the developer to provide a custom implementation of the challenge/response code
  • ResponseMinimumDelaySeconds: An optional property that specifies the minimum number of seconds to wait before which a response or postback is considered valid
  • CutoffWindowSeconds: An optional property that specifies the number of seconds specifying the length of the cutoff window that tracks previous postbacks from each IP address
  • CutoffMaximumInstances: An optional parameter that specifies the maximum number of postbacks allowed by single IP addresses within the cutoff window

Now, fully utilizing the NoBot control requires coding. The NoBot control has the following methods for interacting with it.

  • EmptyUserAddressCache: Clears the list of IP addresses and dates maintained by the NoBot control.
  • GetCopyOfUserAddressCache: Returns key value list of IP addresses and dates when page is accessed by that address.

In addition, the OnGenerateChallengeAndResponse event may be used to utilize a custom challenge and response scenario to validate the submission. This event accepts a second parameter, which is an instance of the jaxControlToolkit.NoBotEventArgs class.

This class has two properties pertinent to our coding. First, the ChallengeScript establishes the JavaScript that should be run within the browser. The RequiredResponse property establishes what the value from the ChallengeScript property should be. These two properties must match for the NotBot control to evaluate to a true value for the IsValid method. Let's take a closer look at the control through example code.

Examples

The first simple example demonstrates basic use of the NoBot control. It utilizes the ResponseMinimumDelaySeconds to set a minimum amount of time between page load and postback to three seconds. A Label control is used to display any error message.

The Click event of the Button control utilizes the NoBot control to signal if submission is valid. It uses the IsValid property of the NoBot control to test it. The output of the call to the IsValid method is stored in an instance of the NoBotState class. The text of the error is displayed in the Label control if the submission is deemed invalid.

<%@ Page Language="C#" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

protected void Button_Click(object sender, EventArgs e) {

NoBotState state;

if (!PageNoBot.IsValid(out state)) {

Label1.Text = "Errors: " + state.ToString();

Label1.Visible = true;

} else {

Label1.Text = "";

Label1.Visible = false;

} }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>NoBot Example</title>

</head>

<body>

<form id="frmNoBotExample" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server">

</asp:ScriptManager>

<div>

Enter your name: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button_Click" />

<br /><br />

<asp:Label ID="Label1" runat="server" ForeColor="Red" Text="Label" Visible="false" />

</div>

<cc1:NoBot ID="PageNoBot" runat="server" Enabled="true"

ResponseMinimumDelaySeconds="3" />

</form></body></html>

If the form is submitted too quickly (under three seconds after loading), then the following message is displayed:

Errors: InvalidResponseTooSoon

The next example builds upon the first example by utilizing the custom challenge and response feature. Basically, it adds two random numbers in a simple JavaScript eval statement. This result is compared against the result in the code; they will match if the page was loaded in the browser where the JavaScript runs.

Also, the GetCopyOf UserAddressCache method of the NoBot control is used to display the list of IP addresses used to submit the page — the addresses are displayed in another ListBox control.

<%@ Page Language="C#" %>

<%@ Import Namespace="System.Collections.Generic" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

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

Random rand = new Random();

int FirstNumber = rand.Next(1000);

int SecondNumber = rand.Next(1000);

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

e.RequiredResponse = Convert.ToString(FirstNumber + SecondNumber);

}

protected void Button_Click(object sender, EventArgs e) {

NoBotState state;

if (!PageNoBot.IsValid(out state)) {

Label1.Text = "Errors: " + state.ToString();

Label1.Visible = true;

} else {

Label1.Text = "";

Label1.Visible = false;

}

StringBuilder sb = new StringBuilder();

foreach (KeyValuePair<DateTime, string> keyValue in NoBot.GetCopyOfUserAddressCache())

{

sb.AppendFormat("{0}: {1}<br />", keyValue.Key.ToString(), keyValue.Value);

}

Label2.Text = sb.ToString();

}

</script>

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server"><title>NoBot Example 2</title>

</head>

<body>

<form id="frmNoBotExample2" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server">

</asp:ScriptManager>

<div>

Enter some text: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button_Click" />

<br /><br />

<asp:Label ID="Label1" runat="server" ForeColor="Red" Visible="false"></asp:Label>

<br /><br />

<asp:Label ID="Label2" runat="server" ForeColor="Red" Visible="true"></asp:Label>

</div>

<cc1:NoBot ID="PageNoBot" runat="server" Enabled="true"

CutoffMaximumInstances="5" CutoffWindowSeconds="10" ResponseMinimumDelaySeconds="3"

OnGenerateChallengeAndResponse="PageNoBot_GenerateChallengeAndResponse" />

</form></body></html>

This second example can be altered to show what happens when the values used in the PageNoBot_GenerateChallengeAndResponse method do not match. Change the following line:

e.RequiredResponse = Convert.ToString(FirstNumber + SecondNumber);

Change it to this code and run the application to see the InvalidBadResponse error message encountered when the values do not match:

e.RequiredResponse = Convert.ToString(FirstNumber + 2);

Some protection

The NoBot control is a nice addition to the ASP.NET toolkit. It offers basic protection from bots with little code. However, it does require AJAX.NET, and JavaScript must be enabled in the browser. I still think CAPTCHA alternatives offer more robust protection.

Are you using any type of anti-spam or bot controls in your applications? Have you used the NoBot control? Share your thoughts with the Web Developer community.

Get weekly development tips in your inbox Keep your developer skills sharp by signing up for TechRepublic's free Web Developer newsletter, delivered each Tuesday. Automatically subscribe today!

About Tony Patton

Tony Patton has worn many hats over his 15+ years in the IT industry while witnessing many technologies come and go. He currently focuses on .NET and Web Development while trying to grasp the many facets of supporting such technologies in a productio...

Editor's Picks

Free Newsletters, In your Inbox