Tuesday, May 27, 2008

Prevent HTML Injection in ASP.Net

What is HTML Injection?

HTML Injection refers to injecting HTML code into a web servers response to alter the content to the end user. HTML injection is one of the technique for hacking and phishing. This is also known as Cross Site Scripting.

The developer must take care of these kind of security Vulnerability.

How To Prevent?

If you are a ASP.Net developer then you must know about the Validation Controls. We can prevent the HTML injection by using Custom Validation Control. It is pretty simple to write the custom logic to prevent HTML injection by using Custom Validation Control.

But I am not going to explain how to put the validation into Custom Validation control. But I am going to explain, that how we can apply the HTML validation across the application without writing redundancy code.

.Net provides facility to extend their control for our own use. We can use those extended controls into our application development.

To extend the control, we just need to inherit our class from the particular control. To create the Custom control of ASP.Net's Custom Validator control, we will need to inherit our class from the System.Web.UI.WebControls.CustomValidator class. Please find below code to create custom control of Custom Validator Control.

namespace CustomControls
{
public class CustomValidator : System.Web.UI.WebControls.CustomValidator
{
private bool m_pastInit;
private bool m_ValidateHtmlInjection = false;

#region Public Properties
[Themeable(false)]
public bool ValidateHtmlInjection
{
get
{
return this.m_ValidateHtmlInjection;
}
set
{
this.m_ValidateHtmlInjection = value;
}
}
#endregion

public CustomValidator()
{
m_pastInit = false;
}

protected override void OnInit(EventArgs e)
{
base.OnInit(e);
m_pastInit = true;
this.SetFocusOnError = true;
this.Display = ValidatorDisplay.Dynamic;
}

protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (this.m_ValidateHtmlInjection)
{
this.ServerValidate += new ServerValidateEventHandler(this.HtmlInjectionServerValidator);
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "HtmlInjectionClientValidator", BuildHtmlInjectionValidationClientSideFunction());
this.ClientValidationFunction = "HtmlInjectionClientValidator";
}
}

private string BuildHtmlInjectionValidationClientSideFunction()
{
const string NEW_LINE = "\n";
const string TAB = "\t";
System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
stringBuilder.Append(NEW_LINE + "<script language=\"javascript\" type=\"text/javascript\">" + NEW_LINE);
stringBuilder.Append(TAB + "function HtmlInjectionClientValidator(source,arguments){" + NEW_LINE);
stringBuilder.Append(TAB + TAB + @"var re = /<[\w]+>/;" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "if(re.test(arguments.Value))" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "{" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + "arguments.IsValid = false;" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "}" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "else" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "{" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + "arguments.IsValid = true;" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "}" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "var reHTMLPattern = new Array('<input', '<select', '<img', '<option', '<textarea', '<span', '<div', '<label', '<h', '<br', '<hr', '<table', '<tr','<th', '<td', '<a', '<body', '<html', '<script', '<link', '<meta', '<iframe', '<p', '<b', '<srtong', '<i','<dd','<dt');" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "if (String(arguments.Value) != 'undefined')" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "{" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + "for(var pattern in reHTMLPattern)" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + "{" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + TAB + "if(arguments.Value.indexOf(reHTMLPattern[pattern])>=0)" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + TAB + "{" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + TAB + TAB + "arguments.IsValid = false;" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + TAB + TAB + "break;" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + TAB + "}" + NEW_LINE);
stringBuilder.Append(TAB + TAB + TAB + "}" + NEW_LINE);
stringBuilder.Append(TAB + TAB + "}" + NEW_LINE);
stringBuilder.Append(TAB + "}" + NEW_LINE);
stringBuilder.Append("</script>" + NEW_LINE);
return stringBuilder.ToString();
}

protected void HtmlInjectionServerValidator(object source, ServerValidateEventArgs args)
{
string regEx = @"<[\w]+>";
string[] halfHtmlTags = { "<input", "<select", "<img", "<option", "<textarea", "<span", "<div", "<label", "<h", "<br", "<hr", "<table", "<tr", "<th", "<td", "<a", "<body", "<html", "<script", "<link", "<meta", "<iframe", "<p", "<b", "<srtong", "<i", "<dd", "<dt" };
bool isValid = !System.Text.RegularExpressions.Regex.IsMatch(args.Value, regEx);

if (isValid)
{
foreach (string halfHtmlTag in halfHtmlTags)
{
if (args.Value.IndexOf(halfHtmlTag) > 0)
{
isValid = false;
break;
}
}
}
args.IsValid = isValid;
}
}
}



The class, expose the property IsHtmlInjectionValidator, this property is not there in the traditional ASP.Net Custom Validator control. The validation control have client side and server side validation methods. Both method behave same. The server side validation method will be used when somebody has disabled the JavaScript support from the browser.



How To Call in ASPX Page?



To add the custom control into the ASPX page, we need to register the assembly into the page. Below is the code to register the assembly...



<%@ Register Assembly="ControlLib" Namespace="CustomControls" TagPrefix="CustomControls" %>


Below is the code for adding Custom Control into the ASPX page,



<CustomControls:CustomValidator runat="server" ID="HtmlTestCustomValidator"
ValidateHtmlInjection="true" ErrorMessage="This is HTML Injection..." ControlToValidate="InjuctionTestTextBox"></CustomControls:CustomValidator>



Other Usage



We can create SQL Injection using same methodology. I keep that for the readers. If you can find how we can do the SQL Injection validation please share with all. Otherwise I will post the SQL Injection into my next post.



Happy Coding....

No comments: