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....

Friday, May 23, 2008

10 Tips For Effective Reading And Learning


  1. Relax Before Reading
    Concentration is key factor of effective reading and learning. You will need to relax your mind and swipe off your thoughts. You brain need to be empty by thoughts before you start the reading. It is like giving space to new thoughts which are going to be arise during your reading. Your emotions need to be in neutral before reading. That will give you chance to evaluate your reading. You can do some meditation or listen to soft music before start of reading. Most of all fighter pilots and F1 racers adopt this technic before go to the flight or in race. Try it, it is really effective. 
  2. Go Slow with the Reading Never do hurry with your reading. Don't just read. Go very slow with reading. Try to understand each and every word written by author. Try to ask questions to your own self and find the answer. The more deeply you force your brain to think, the better chance you have of learning and remembering.
  3. Take Challenges of Exercises. Authors keep exercises in book for you. But what if they do that for you? You will never attempt the challenge. It will be like, you are hungry and somebody is eating on behalf of you....
  4. Write Your Own Notes In Book
    Its not bad to use Pencil to write something in your books. You can write lots of your own notes in book. It is really good practice to improve your understanding of what you are reading. Some people don't like to write anything into book, as book get spoil. In this case you can write your notes into separate notebook or even you can use sticky notes. But please write your thoughts.
  5. Give Enough Time To Your Brain
    The process of transferring the reading into long-term memory happens after stop reading. Our brain needs time to do processing. If we keep anything new or challenging during the processing time, Some of what you learned might be lost. It is recommended to read before you go to bed.
  6. What Your Brain Need?
    The performance of Brain is depend on lots of things. But we can follow few basic things to make it more efficient. The brain works best in a nice bath of fluid. Research said that Dehydration decreases cognitive function of brain. The dehydration can happened before we feel thirsty. So, keep drinking enough water while reading [But this also can cause lots of washroom visit and can break your concentration, so keep it in your own limit]. Brain also need good sound sleep. To learn at it's best, give enough sleep to you brain [At least 6-8 hours]. And last but not least, you brain need food. Please eat proper to nourish your brain. Protein, Vitamins, Sodium and Iodine are very important for your brain.
  7. Speak it out Loud.
    Speaking activates a different part of your brain. If you are trying to understand something, or increase your chance of remembering it later, say it out loud. You can discuss what you have learned or read with some of your friend (Or even with your own self in front of mirror). The discussion will bust the confidence in you. And you will see that you are learning quickly. During discussion you might come out with new ideas you had not known were there when you were reading about it.
  8. When To Stop
    You should know that when to stop reading. Your brain may overloaded. You should understand the limitation of your brain (I can not read more then 45 minutes in row, it's limitation of my brain). Now one very obvious question, how to know when to stop? If you find yourself starting to forget what you just read, or the characters start dancing on page, then that is the right time to stop reading and have some break.
  9. Feel it !!
    You must feel the importance of what you are reading or learning. Your brain need to take the reading seriously to learn effectively. Your brain will never take the reading seriously if it don't know the importance of that. 
  10. Practices
    Apply what you have read in your life. Try to put that in your everyday practice. Theoretical and practical both are the different knowledge. You need to apply your theoretical knowledge in your practical life. Coz all reading and learning will not matter until you start practicing that in your routine life. Books will show you the path (Theory) but to walk on the path (Practical) is your responsibility. I might have read everything written or printed about the Everest, but to archived the Everest is complete different thing. My reading and knowledge about the Everest only worth if, I climb and archived the Everest.

Wednesday, May 21, 2008

SQL Server Reporting Service (SSRS) - HTTP Status 401 Unauthorized Error

I am going to continue on writing article on SQL Server Reporting Services (Its because, it is providing me good fame on http://forums.asp.net, LOL smile_wink).

We have to deploy the reports on the the Reporting Services Virtual Directory (I can write the whole different article on the Reporting Deployment, but may be next time. Right now we don't want to go deep into that.). The Reporting Server Virtual Directory may exist on the different server. It is recommended to keep anonymous access off for Reports virtual directory if you are going to call reports on the web.

The anonymous access allows any user to access the page. But now when we are keeping anonymous access off for the Reports, it can create problem while fetching the report inside the Report Viewer control on any ASPX page.

The Report server will expect authorized user to access the reports. This can be done by two ways.

  1. Passing the Report Server User Credentials with the Reports.
  2. Forms Authentication on Reporting Server.

Today, I am going to explain that How can we pass the User Credentials of the Reporting Server with the report call.

We need to Create one sealed class to perform this action. This class need to be inherited from IReportServerCredential interface.

    [Serializable]
public sealed class ReportServerNetworkCredentials : IReportServerCredentials
{
#region IReportServerCredentials Members

/// <summary>
/// Provides forms authentication to be used to connect to the report server.
/// </summary>
/// <param name="authCookie">A Report Server authentication cookie.</param>
/// <param name="userName">The name of the user.</param>
/// <param name="password">The password of the user.</param>
/// <param name="authority">The authority to use when authenticating the user, such as a Microsoft Windows domain.</param>
/// <returns></returns>
public bool GetFormsCredentials(out System.Net.Cookie authCookie, out string userName,
out string password, out string authority)
{
authCookie = null;
userName = null;
password = null;
authority = null;

return false;
}

/// <summary>
/// Specifies the user to impersonate when connecting to a report server.
/// </summary>
/// <value></value>
/// <returns>A WindowsIdentity object representing the user to impersonate.</returns>
public WindowsIdentity ImpersonationUser
{
get
{
return null;
}
}

/// <summary>
/// Returns network credentials to be used for authentication with the report server.
/// </summary>
/// <value></value>
/// <returns>A NetworkCredentials object.</returns>
public System.Net.ICredentials NetworkCredentials
{
get
{
string userName = "SERVERUSERNAME";
string domainName = "DOMAIN";
string password = "somepassword";

return new System.Net.NetworkCredential(userName, password, domainName);
}
}

#endregion
}



How to Utilize the ReportServerNetworkCredentials Class in your Report call on Page_Load event...



protected void Page_Load(object sender, EventArgs e)
{
myReportViewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Remote;

// Here we are going to pass the ReportServerCredentials to the Report Viewer.
myReportViewer.ServerReport.ReportServerCredentials = new ReportServerNetworkCredentials();

ReportServerLoaction = ConfigurationManager.AppSettings["REPORT_SERVER_PATH"];
myReportViewer.ServerReport.ReportServerUrl = new Uri("http://MyReportServer/Reports/");
myReportViewer.ServerReport.ReportPath = "TempReports/MyFirstReport";
myReportViewer.ShowParameterPrompts = false;
myReportViewer.ShowPrintButton = true;

Microsoft.Reporting.WebForms.ReportParameter[] reportParameterCollection = new Microsoft.Reporting.WebForms.ReportParameter[1];
reportParameterCollection[0] = new Microsoft.Reporting.WebForms.ReportParameter();
reportParameterCollection[0].Name = "ClientID";
reportParameterCollection[0].Values.Add("49020644-63AA-4D92-81A1-8F85D49ACF67");

myReportViewer.ServerReport.SetParameters(reportParameterCollection);
myReportViewer.ServerReport.Refresh();
}



Please feel free to comment on the article. Critics are highly appreciated.

Saturday, May 10, 2008

SQL Server Reporting Services (SSRS) Versus Browser Compatibility

 

Microsoft has released SQL Server Reporting Services(SSRS) as server based report generation and development environment in 2004. It was released as SQL Server 2000 extension. SSRS has been released directly to the competition of Crystal Report and other Business Intelligence tools. The current version of SSRS is shipped with SQL Server 2005.

The file format of SSRS reports is .rdl. The RDL is XML. The RDL can be exported to PDF, XML, Excel, TIFF, CSV, HTML. Apart from this, you can call the report by simple URL.

Sounds Good...!!!!!

But, with all these coolest features of SSRS, there are plenty of bugs too. First ever bug I encounter is Browser Compatibility. There is pretty big issue with SSRS reports browser compatibility. The reports are best view in only IE6 and above. In this competitive world, we need to provide browser compatible websites. SSRS can be big hurdle in your website against browser compatibility.

We experienced a problem with the multivalue parameter dropdown in ReportViewer control in FireFox. It was working fine in IE. The calendar control and the multivalue dropdown was having problem. The problem caught me when I click on the calendar control, the calendar appears and then quickly disappeared before I can select anything. It was just in frequence of second. Wow, it was pretty quick and it became a challenging game for me to catch it. But Microsoft was very quick and I never could catch calendar.

The problem was with ReportViewer control provided by VS2005. When we call report directly in Firefox browser using report URL, it was working perfectly fine. So, finally we came to conclusion that, the problem is only due to ReportViewer control.

The solution to resolve the issue is very strange. We need to remove the DOCTYPE tag from the HTML. Removing DOCTYPE tag can create lots of issues with HTML and CSS layouts. But we have to rectify other issues.

Developers of ReportViewer control has used some nonstandard methods and attributes like onactive event. The page contains specific DOCTYPE, will not parse such events. We tried to use other DTDs like, HTML 4.0 and HTML 5.0 but nothing help. Finally we removed the DOCTYPE and problem get solve (And other design related problem start arising smile_sad).

For more in SSRS please visit Paresh Jagatiya's Weblog.

Friday, May 2, 2008

Date Format Conversion

The whole world is divided into different time zones and cultures. Every country has own style to display date and time format. Like, in USA the date has been displayed in “mm/dd/yyyy” format while in Great Britain and India the date has been displayed in “dd/mm/yyyy” format. In the web era, it’s always tough to provide culture oriented user interface. It is easy to display the date in specific format on page using ASP.net. Programmer can easily use .ToString(“dd/mm/yyyy”); to display the date into British format. But it’s not easy to store date into server with formatting.

Let’s take one scenario to understand this, I have a webpage which sense the user’s current time zone and display the date according to that. But the website is hosted on the USA based server. So the SQL Server for the Website will have the “mm/dd/yyyy” format. The SQL Server will expect the date in “mm/dd/yyyy” format. This can create problem when we provide such user interface which accept the date into “dd/mm/yyyy” format. We have to convert the date back into server’s date format before saving into database.

There is no any direct method to convert the date format with DateTime type. Probably Convert.ToDateTime() provide such facility with iFormatProvider interface. But, I really don’t know how to use that. So, I found one another work-around to convert the date in other format.

It’s very tricky to convert the date format from “dd/MM/yyyy” to “mm/dd/yyyy” in .Net 2.0. Below is function, using that programmer can convert any date in any format to the server’s date format.


public DateTime ConvertDate(string Date, string CurrentDateFormat)
{
try
{
return DateTime.ParseExact(Date, CurrentDateFormat, new CultureInfo(Thread.CurrentThread.CurrentCulture.Name));
}
catch
{
throw;
}
}