ASP.NET Data Binding and AntiXss Encoding

Hi RV here again...

Last time I looked at ASP.NET controls and few common scenarios where you need to use encoding. Couple of weeks back we looked at a sample data binding scenario. This time lets exclusively look at various ASP.NET data binding techniques and how to use AntiXss to encode the output.

Scenario #1: Eval()

Most common way of data binding in ASP.NET is by using Eval() method. Here is an ASP.NET label control bound to the "Comments" field of the data source.

    1: <!--Usage #1-->
    2: <asp:Label runat="server" ID="CommentsLabel" Text='<%# Eval("Comments") %>' />
    3: <!--Usage #2-->
    4: <asp:Label runat="server" ID="CommentsLabel" 
    5:                 Text='<%#DataBinder.Eval(Container.DataItem,"Comments") %>'/>

By definition Eval() method uses reflection to bind the column at runtime this may affect performance of the application. Apart from the performance, as Eval() uses reflection it is generally inadvisable. Instead you should use Container.DataItem directly for binding and wrap it with AntiXss.HtmlEncode method to protect from XSS as shown below.

    1: <asp:Label runat="server" ID="CommentsLabel" 
    2: Text='<%#Microsoft.Security.Application.AntiXss.HtmlEncode
    3: (((System.Data.DataRowView)Container.DataItem)["Comments"].ToString()) %>'/>

By using Container.DataItem directly we improve performance and can use AntiXss with it. Note that you can still use AntiXss.HtmlEncode on just the Eval() method.

Scenario #2: Bind()

Bind() is another way of data binding in ASP.NET. Here is the same ASP.NET label control bound to the "Comments" field using Bind().

    1: <asp:Label runat="server" ID="CommentsLabel" Text='<%#Bind("Comments") %>'/>

Bind() is a very special way of data binding in ASP.NET. Unlike Eval() Bind() is not a method call so when ASP.NET compiler encounters Bind() statements, it will generate additional code for data binding. If you look at the code created in the ASP.NET Temporary Files Folder, it in fact has DataBinder.Eval statement. Unfortunately due to this there are limitations on what you can do with a Bind() statement. One limitation is that you cannot wrap Bind() statements with any other method calls.

    1: //Code generated in the temporary file for the Bind() statement
    2: dataBindingExpressionBuilderTarget.Text = 
    3: System.Convert.ToString(this.Eval("Comments"), 
    4:     System.Globalization.CultureInfo.CurrentCulture);

For more information on this behavior check this blog post. In essence if you use Bind() statements, you should convert the code to use Eval() statements and wrap them with AntiXss library as shown in scenario #1 above.

Scenario #3: <%# %>

In some cases you might want to just bind some data to a control or a html element. This can be achieved by using <%# variable %> and Page.DataBind(). Here is some sample code.

    1: //variable declaration in the code behind file
    2: public string hyperLink="https://www.microsoft.com";
    3: Page.DataBind();
    4:  
    5: <!--In the ASP.NET page-->
    6: <a href="<%# this.hyperLink %>">Microsoft Corporation</a>

Although this is somewhat a strange way to do this, it sure illustrates the point of data binding. In this case, by simply wrapping the this.hyperLink in AntiXss.HtmlEncode would fix the problem.

    1: <%# Microsoft.Security.Application.AntiXss.HtmlEncode(this.strLocation) %>

As we have seen in the above scenarios Bind() is the only case where you will not be able to protect from XSS using encoding, so the best option is to change the ASP.NET code to use Eval() statement.