Welcome to Professional ASP.NET - Chris Love's Official Blog Sign in | Join | Help

Chris Love's Official ASP.NET Blog

Chris Love's Helpful tips, tricks and pragmatic development knowledge for the ASP.NET world.
Add to Technorati Favorites


ASP Insider
Preventing Cross-Site Script Attacks with a Custom TextBox Control

Cross-Site Scripting attacks are still a frequent occurance across the web.  Fortunately the ASP.NET framework has a built-in protection against this type of attack.  But as good as that is, it is still actually limited to a certain degree.  So it is a good practice to add your own protection layers to applications, guarding against as many unexpected attacks as possible.

A brief explanation of a Cross-Site Scripting attack would be a hacker injecting some client-side (JavaScript) into the page to usually transfer sensative data to their server.  It could also be as simple as changing the data that is displayed on your page to visitors.  The point is this can be extremely dangerous and we need to do as much as possible to mitigate our attack surfaces.

A few years ago I wrote a simple Label control, ExSafeLabel, to help guard against this type of attack.  I think it is still listed on the http://www.asp.net/ control gallery, even though I do not have the control available anymore (sorry).  It was written in the early days of ASP.NET 1.0.  ASP.NET 1.1 introduced some core protection against these types of attacks with the ValidateRequest page directive.  You have to manually set this to false in order for HTML and JavaScript tags to be submitted to a page.  As good as this is, it still does only basic protection for us. 

I have thought about this issue for some time now and thought it might be a good idea to create my own textbox that would help lower the potential of this type of attack, ExSafeTextBox.  This entry will be an introduction to this control and I will show how to stop some basic stuff, and I hope to expand this control over the next few weeks to stop as much as possible.

The ExSafeTextBox is a simple Web Control that inherits from TextBox.  I have added one boolean property AllowAllTags as a flag to apply protection or just let things pass through.  A second property overrides the Text property of the TextBox control and applies our protection.

    1 Imports System.Text.RegularExpressions

    2 Imports System.Web.UI.WebControls

    3 Imports System.Web.UI

    4 

    5 ''' <summary>

    6 '''

    7 ''' </summary>

    8 ''' <remarks></remarks>

    9 Public Class ExSafeTextBox

   10     Inherits System.Web.UI.WebControls.TextBox

   11 

   12     ''' <summary>

   13     '''

   14     ''' </summary>

   15     ''' <value></value>

   16     ''' <returns></returns>

   17     ''' <remarks></remarks>

   18     <DefaultValue("False"), Localizable(True), Bindable(True, BindingDirection.TwoWay), _

   19         PersistenceMode(PersistenceMode.EncodedInnerDefaultProperty)> _

   20         Public Property AllowAllTags() As Boolean

   21         Get

   22             Dim bAllowAllTags As Boolean = Me.ViewState.Item("AllowAllTags")

   23             If IsNothing(bAllowAllTags) = False Then

   24                 Return bAllowAllTags

   25             End If

   26             Return False

   27         End Get

   28         Set(ByVal value As Boolean)

   29             Me.ViewState.Item("AllowAllTags") = value

   30         End Set

   31     End Property

   32 

   33     ''' <summary>

   34     '''

   35     ''' </summary>

   36     ''' <value></value>

   37     ''' <returns></returns>

   38     ''' <remarks></remarks>

   39     <DefaultValue(""), Localizable(True), Bindable(True, BindingDirection.TwoWay), _

   40         PersistenceMode(PersistenceMode.EncodedInnerDefaultProperty)> _

   41     Public Overrides Property Text() As String

   42         Get

   43             Dim text1 As String = MyBase.Text

   44 

   45             If String.IsNullOrEmpty(text1) Then

   46                 Return String.Empty

   47             End If

   48 

   49             If AllowAllTags Then

   50                 Return Regex.Replace(text1, "", String.Empty)

   51             End If

   52 

   53             Return Regex.Replace(text1, "<[^>]*>", String.Empty)

   54 

   55         End Get

   56         Set(ByVal value As String)

   57             MyBase.Text = value

   58         End Set

   59     End Property

   60 

   61 

   62 End Class

 

The protection comes from executing a regular expression replace method on the text entered in the Textbox.  This expression removes any HTML tag from the text.  To actually use this control we can add it to Visual Studio's control Toolbox or hand code things in our web project.  I have personally included this control in my ExBaseFuncs Library, so you will see it referenced in the code below.  You could also add the control source to your App_code directory, instead of a class library.

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="scratch.aspx.vb" Inherits="scratch"

ValidateRequest="false" %>

<%@ Register Assembly="ExtremeWebWorks.ExBaseFuncs" Namespace="ExtremeWebWorks" TagPrefix="cc1" %>

<%@ Register Assembly="ExtremeWebWorks.ExBaseFuncs" Namespace="ExtremeWebWorks" TagPrefix="cc1" %>

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

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

<head runat="server">

<head runat="server">

<title>Untitled Page</title>

</head>

<body>

<body>

</head>

<body>

<body>

<form id="form1" runat="server"><div>

&nbsp;<cc1:ExSafeTextBox ID="ExSafeTextBox1" runat="server" Width="457px"></cc1:ExSafeTextBox>

<asp:Button ID="Button1" runat="server" Text="Button" /></div></form>

</body>

</html>

</html>

To see this in action let's enter a potentially harmful script in the textbox and then echo it back with a response.write().  Notice I turned off the ValidateRequest directive on the page, I did this to test this simple script.

Corss-Site Scripting Attack

 

This is an over simplified example, that if droped on the page would cause an alert message box to be displayed.  But you can see that this could be potentially much more damaging.  With all the great Ajax stuff out there and the bridging technology, think about what could be sent back to the potential bad guy.

Ouch! 

Ouch this hurts.  Fortunately, the ExSafeTextbox has protected us and we just get some harmless text echoed back on the page.

My next step is to add protection against encoded attacks.  It is not that hard for an attacker to encode their JavaScript as ASCII characters, so it just looks like a long string of numbers on the page.  Many Black Hat SEO companies use this technique to game the search engine results by doing hidden redirects.  This attack would be real hard to pull off, but technically could be done.

Safe!

These types of attacks are not limited to Microsoft technolgies, but to any web site on any platform.  Despite how bad our platform gets pounded by the general media, it is probably one of the more robust, secure platforms and has many safe guards in place.  But do not feel safe, instead be steadfast and alert and you will reap the rewards.

 

Posted: Saturday, December 02, 2006 12:30 PM

by Chris Love

Comments

Tom said:

Great control, incredibly simple, but exactly what I needed. I've taken this and modified it to inherit SharePoint's InputForTextBox in C# and it's working great. Thank you
# September 28, 2008 2:28 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS