asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search








Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Fighting Spambots with .NET and AI -- Cont'd
By Adnan Masood


  • email this article to a colleague
  • suggest an article

    Writing Your Own CAPTCHA Application

    Recently I read two articles covering the visual human-proofing solution. One was in DDJ October 2003 issue by Paul Tremblett titled "Java 2D & Web Pages". It explains how incorporating server-side Java 2D into Web application components is an easy way to deliver dynamic data. The second one was Lee Bruno's "Baffling the Bots" published in Scientific American, November 2003. These readings motivated me to develop a sample application for the .NET platform to protect forms from automated registration and spam bots.

    Below are image generation programs which prevent automatic form submission by robots. If a Web application is being cluttered with spam, automatic registrations, automatic forum or classified ad submissions, you can use a visual CAPTCHA in your Web forms that only a human can recognize.

    ASP.NET is loaded with image generation and manipulation capabilities. Unlike its precursor ASP 3.0, ASP.NET can exploit the full power of the .NET Framework and doesn't need external library support for on-the-fly image handling. The System.Drawing class provides the capability of creating images in memory and then rendering them through an output stream on the browser. The following code behind file, onthefly.aspx.vb, explains the process. The purpose of this exercise is to create an image dynamically on the basis of parameters passed through a query string. In order to draw on a bitmap, we need HTTPContext, which is the browser's stream handler for instantiating the System.Drawing.Bitmap object. Its constructor takes pixelFormat as a parameter and returns a 110x50 canvas for drawing. Keep in mind that this whole process is being done in memory and will be rendered later for a user to experience in a browser when pageContext is flushed. After that, we need a graphics object to handle drawing on raster, i.e. the bitmap memory map we have. An instance of the graphics object will invoke FillRectangle and DrawString to draw a rectangle and parameter text on the canvas. Later this canvas will be flushed on an output stream as a gif MIME type (as seen in the picture below).

    Example 1.19: Demo for on the fly image generation - IE foreground - VS IDE background

    '// Filename: onthefly.aspx.vb

    '// Author: Adnan Masood

    '// Last updated: 12/07/03

     

    '// Importing the libraries for drawing operations

    Imports System

    Imports System.Drawing

     

    '// Class OntheFly declaration

    PublicClass OntheFly : Inherits System.Web.UI.Page

    '//Page_Load event overriding

    PrivateSub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Load

    '//Getting HTTPContext

    Dim pageContext As System.Web.HttpContext

    pageContext = System.Web.HttpContext.Current

    '//Reading the parameter

    Dim strText AsString = Request("param")

    '//Create the memory map

    Dim raster As Bitmap

    Dim pixFormat As Imaging.PixelFormat

    pixFormat = Imaging.PixelFormat.Format32bppArgb

    '// Create a memory image with dimensions 110x50

    raster = New Bitmap(110, 50, pixFormat)

    Dim graphicsObject As Graphics

    graphicsObject = Graphics.FromImage(raster)

    '// Instantiate object of brush

    Dim objBrush As SolidBrush = New SolidBrush(Color.Yellow)

    '//Creating a font object with Arial size 10 and bold

    '//public Font(string, float, FontStyle)

    Dim objFont As Font = New Font("Arial", 10, FontStyle.Bold)

    '//Set the background half rectangle blue

    '//Method Signature: FillRectangle (const Brush *brush, INT x, INT y, INT width, INT height);

    graphicsObject.FillRectangle(New SolidBrush(Color.Blue), 0, 0, 55, 50)

    '//Writing the string on image

    graphicsObject.DrawString(strText, objFont, objBrush, 0, 0)

    '//Flushing the graphics object

    graphicsObject.Flush()

     

    '//Setting the response header content MIME type

    pageContext.Response.ContentType = "image/gif"

    '//Saving the file to output stream to be displayed in browser

    raster.Save(pageContext.Response.OutputStream, Imaging.ImageFormat.Gif)

    '//Flushing to the Response

    pageContext.Response.Flush()

    EndSub

    EndClass

    Listing: OntheFly.aspx.vb

    OntheFly.aspx.vb is the code behind file for OntheFly.aspx. It contains the following code.

    <%@ Page Language="vb" Src="OntheFly.aspx.vb" Inherits="OntheFly"%>

    Listing: OntheFly.aspx

    The following figure (Example 1.20) demonstrates output as an image. For any particular param=xyz, this code will generate an image and render it on a browser. When written on an image as part of a binary file, text can't be read like HTML, and spammers would need special techniques to comprehend what's written. This simple example can be enhanced for use in email address protection schemes for forums, blogs, etc. With good cache handling, performance shouldn't be an issue.

    Example 1.20: Serving dynamic (on the fly) image from an ASP.NET file for passed query string parameter.

    A Dictionary Based CAPTCHA Implementation

    This example is a bit lengthy and detailed as it involves the development and usage of a full-fledged CAPTCHA program. This program dynamically generates dictionary-based CAPTCHA, asks for input before proceeding, and verifies the status.

    The flow of this program can be seen below. While filling out the form for some fictitious forums, the user is asked to fill in the text shown in the picture to verify if the user is human. This program dynamically selects backgrounds from a variety of provided images and text from OGDEN's Basic English dictionary. Fonts also differ from letter to letter, making it difficult for an attacking OCR to recognize. The complete listing, along with dictionary database file, is provided with this article and briefly discussed below.

    Figure: 2.1 Demonstrates a signup form for forums

    If the wrong word is entered, the user cannot proceed and the following error message displays.

    Figure: 2.2 Demonstrates an error while signing up for forums

    Next time, to the astonishment of a bot, a new image with a different background and a different word will appear. An application architect should consider how many times entries should be allowed and log them to make sure the program is not being an unwelcomed barrier instead of a security measure. There should be alternatives (sound for instance) available for people with disabilities.

    Figure: 2.3 Demonstrates a signup form for forums

    Upon entering the right word, yourself in this case, the program lets the user through and one can write further processing instructions after it.

    Figure: 2.4 Demonstrates a successful signup for forums

    Now let's see the anatomy of this application.

    Below is a screenshot for OGDEN's Basic English dictionary database. Every column contains an alphabet which gets picked up randomly to generate CAPTCHA image.

    Figure: dictionarydb. Demonstrates OGDEN's Basic English dictionary database for application.

    There are three main files involved in this coding:

    captchaForm.aspx: This file contains code for picking a random dictionary word and passing it onto captcha.aspx. Captcha.aspx's code behind file, captcha.aspx.vb, processes it and renders the image to the browser. This file also contains code for processing the form and checking if CAPTCHA's value is entered correctly. It also contains code to establish connection with dictionary.mdb, read a random word, and handle session.

    captcha.aspx.vb: This is the code behind file for captcha.aspx. It performs image generation tasks. The code in this file picks up a background pattern randomly from a background folder and writes the text string passed by captchaform.aspx. This file also selects the font face and size randomly to make images difficult for machines to read.

    dictionary.mdb: This access database repository contains OGDEN's Basic English dictionary entries.

    Along with comments, listings are quite self explanatory.

    <!--

    '// Filename: captchaForm.aspx

    '// Author: Adnan Masood

    '// Last updated: 12/08/03

    -->

     

    <%@ Import Namespace="System" %>

    <%@ Import Namespace="System.Data" %>

    <%@ Import Namespace="System.Data.OleDb" %>

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

     

    <HTML>

    <head>

    <script runat="server">

    // Pageload event

    void Page_Load(object Source, EventArgs E)

    {

    // If form is not posted than assign the selectWord return to session

    if (!IsPostBack)

    Session["param"] =selectWord();

    // Else check if session's value is same as that of Captcha's entered value

    // in the form and assign appropriate message to innertHtml of label

    else

    {

    if (String.Compare(Convert.ToString(Session["param"]),Convert.ToString(Request.Form["CAPTCHA"]))==0)

    lblstatus.InnerHtml= "Thanks for Registeration with our Forums";

    else

    lblstatus.InnerHtml= "Error Occured! Value of Image is not correct, please <a href=captchaform.aspx> re-enter </a>";

    }

    }

    // Select word method

    // Return type String of random word from dictionary

    // Dictionary is based on OGDEN's BASIC ENGLISH

    // http://ogden.basic-english.org/basiceng.html

     

    public String selectWord () {

    // The Connection string referencing the MDB file

    String ConnectionString = "Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("dictionary.mdb") + ";";

    // Datareader object

    OleDbDataReader objReader;

    // Creating an array of 26 characters (alphabets in dictionary database as columns)

    char[] columns = newchar[26];

    // Adding the column names in the array

    // uses the ASCII character conversion for selecting values

    // from A- Z

    for (int a=65; a<65+26; a++)

    columns[a-65] = (char)a;

    // Query String for selecting a random column from spelling list database

    String QuerySQL = "SELECT " + columns[(new Random().Next(26))] + " FROM spellList";

    // Opening the connection

    OleDbConnection objConn = new OleDbConnection(ConnectionString);

    // Creating new command object

    OleDbCommand objCmd = new OleDbCommand();

    // Assigning command text

    objCmd.CommandText = QuerySQL;

    // Assigning the connection to command object connection attribute

    objCmd.Connection = objConn;

    // Instantiating a random class object

    Random randomSeed = new Random();

    // Creating a random seed selector

    int randomSeedSelector=0;

    // An string character with maximum capacity for dictionary column

    String[] selectedIndex = new String[700];

    String str = "";

    // This code segment opens the connection and read the dictionary

    try

    {

    objConn.Open();

    objReader = objCmd.ExecuteReader();

    while (objReader.Read()) {

    str = objReader.GetValue(0).ToString();

    if (str.Length != 0) {

    selectedIndex[randomSeedSelector] =str;

    randomSeedSelector++;

    }

    }// Ends While

    str = selectedIndex[randomSeed.Next(randomSeedSelector)];

    } // Ends Try

    catch (Exception Err)

    {

    // The Error Catching operations

    }

    finally

    {

    objConn.Close();

    }

    // Returns the selected string

    return (str);

    }// ends function

     

    </script>

    </head>

    <body>

    <% //Checking for postback for initial processing of form.

    if (!IsPostBack) { %>

    <form runat="server">

    <P align="left"><STRONG><FONT size="5">Signup for Forums</FONT></STRONG></P>

    <P>

    <TABLE id="Table1" height="200" cellSpacing="1" cellPadding="1" width="704" border="1">

    <TR>

    <TD>

    <P>Name</P>

    </TD>

    <TD><INPUT id="Text1" type="text" name="name"></TD>

    </TR>

    <TR>

    <TD>Email Address</TD>

    <TD><INPUT id="Text2" type="text" name="email"></TD>

    </TR>

    <TR>

    <TD>

    <P><IMG src="http://localhost/captcha/example2/captcha.aspx"></P>

    <P>Enter the text above into the box on right.</P>

    </TD>

    <TD><INPUT id="Text3" type="text" name="CAPTCHA"></TD>

    </TR>

    <TR>

    <TD><INPUT id="Submit1" type="submit" value="Submit" name="Submit1"><INPUT id="Reset1" type="reset" value="Reset" name="Reset1"></TD>

    <TD></TD>

    </TR>

    </TABLE>

    </P>

    </form>

    <% }

    //Setting lable's status accordingly

    else

    { %>

    <td id="lblstatus" runat="server"></td>

    <% }%>

    </body>

    </HTML>

     

    '// Filename: captcha.aspx.vb

    '// Author: Adnan Masood

    '// Last updated: 12/08/03

    Imports System

    Imports System.Drawing

    Imports System.String

    Imports System.Drawing.Image

     

    namespace com.axisebusiness.OnlineImage

    '// Importing the libraries for drawing operations

     

    '// Class OntheFly declaration

    PublicClass CAPTCHA : Inherits System.Web.UI.Page

    '//Page_Load event overriding

    PrivateSub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Load

    '//Getting HTTPContext

    Dim pageContext As System.Web.HttpContext

    pageContext = System.Web.HttpContext.Current

    '//Reading the parameter from session this time

    Dim strText AsString = Session("param")

    '//Create the memory map

    Dim raster As Bitmap

    Dim pixFormat As Imaging.PixelFormat

    pixFormat = Imaging.PixelFormat.Format32bppArgb

    '// Select an memory image from file of 290x80px

    '// in the backgrounds folder named backX.jpg

    Dim graphicsObject As Graphics

    Dim imageObject as System.Drawing.Image = System.Drawing.Image.FromFile(Server.Mappath("backgrounds\\back" & new Random().Next(5) & ".jpg"))

    '// Creating the raster image object

    raster = new Bitmap (imageObject)

    '//Creating graphics object

    graphicsObject = Graphics.FromImage(raster)

     

    '// Instantiate object of brush with black color

    Dim objBrush As SolidBrush = New SolidBrush(Color.Black)

     

    Dim objFont As Font

    dim a asInteger, myFont asString, str asString

     

    '//Creating an array for most readable yet cryptic fonts for OCR's

    '// This is entirely up to developer's discretion

    dim crypticFonts(11)

    crypticFonts (0) = "Arial"

    crypticFonts (1) = "Verdana"

    crypticFonts (2) = "Comic Sans MS"

    crypticFonts (3) = "Impact"

    crypticFonts (4) = "Haettenschweiler"

    crypticFonts (5) = "Lucida Sans Unicode"

    crypticFonts (6) = "Garamond"

    crypticFonts (7) = "Courier New"

    crypticFonts (8) = "Book Antiqua"

    crypticFonts (9) = "Arial Narrow"

    crypticFonts (10) = "Estrangelo Edessa"

     

    '//Loop to write the characters on image

    '// with different fonts.

    For a=0 to strText.Length-1

    myFont = crypticFonts(new Random().Next(a))

    objFont = New Font(myFont, 20, new FontStyle().Bold)

    str = strText.substring(a, 1)

    graphicsObject.DrawString(str, objFont, objBrush, a*20, 35)

    graphicsObject.Flush()

    next

    '//Flushing the graphics object

    graphicsObject.Flush()

     

    '//Setting the response header content MIME type

    pageContext.Response.ContentType = "image/gif"

    '//Saving the file to output stream to be displayed in browser

    raster.Save(pageContext.Response.OutputStream, Imaging.ImageFormat.Gif)

    '//Flushing to the Response

    pageContext.Response.Flush()

    EndSub

     

    EndClass

     

    Endnamespace

     

     

    Filename: Captcha.aspx:

    <%@ Page Language="C#" Src="Captcha.aspx.vb" Inherits="com.axisebusiness.OnlineImage.Captcha"%>

    As you might have noticed, this listing also demonstrates how one can use different languages in the same program (C# and VB.NET in my case). I don't claim that the CAPTCHAs generated by this program are un-crackable, but they can take on a mediocre spambot pretty well.

    <-- Introduction   Delivering and Invoking CAPTCHA from Web Services -->

  • Supporting Products/Tools
    AspEncrypt
    Built around the Microsoft CryptoAPI, AspEncrypt helps you harness all major encryption and hashing algorithms such as DES, Triple-DES, RC2, RC4, RSA, MD5 and SHA1 in just a few lines of code. The component can be used in tandem with AspEmail to send encrypted and signed mail in the industry-standard S/MIME format, or with AspUpload to encrypt files as they are being uploaded. AspEncrypt can also be used to issue and manage X.509 digital certificates.
    [Top]
    AspPDF
    AspPDF is an ASP/ASP.NET component which enables generation and management of documents in PDF format. Features include advanced text formatting, font embedding, form fill-in, images, tables, content and page extraction, document stitching, encryption, digital signatures, and more.
    [Top]
    Other Articles
    Feb 3, 2005 - ASP.NET Mixed Mode Authentication
    In many web applications it is desirable for both intranet users and external parties to be able to seamlessly log onto the system. The problem this raises is that it is not easy to allow intranet users to log in via Windows integrated authentication while also allowing external parties to log in to the same application using standard forms authentication. This article will show you one way to achieve the best of both worlds when it comes to authentication.
    [Read This Article]  [Top]
    Dec 8, 2004 - Designing Role-Based Security Models for .NET
    In this article, Michele Leroux Bustamante discusses authentication, authorization and role-based security in .NET. Along the way, he provides some best practices for implementing role-based security in some typical .NET application scenarios including rich clients, Web applications, and Web services.
    [Read This Article]  [Top]
    May 11, 2004 - SharePoint Security and .NET Impersonation
    When implementing custom components that require access to restricted resources, implicit impersonation must be used. Jay Nathan shows how to create a class that makes using .NET Impersonation a snap.
    [Read This Article]  [Top]
    Mar 10, 2004 - Intellectual Property Protection and Code Obfuscation
    Learn about the execution process of CLR-based programs and how to protect your applications from being easily disassembled back into source code.
    [Read This Article]  [Top]
    Feb 24, 2004 - How to Send Secure Mail in ASP-Based E-Commerce Applications - Part II
    Businesses that utilize encrypted e-mail may find Secure Multipurpose Internet Mail Extensions (S/MIME) to be somewhat restrictive. This article shows how to use security features in PDF as an alternative to S/MIME.
    [Read This Article]  [Top]
    Feb 2, 2004 - Fighting Spambots with .NET and AI
    Bill Gates, in a recent interview, predicted the end of spam by 2006. One of the methods he mentioned involved a challenge only a real live person could handle. Adnan Masood shows how to use AI and .NET to create a user verification scheme that incorporates similar concepts Gates alluded to.
    [Read This Article]  [Top]
    Jan 21, 2004 - Configuring .NET Code Access Security