Real World XSS Vulnerabilities in ASP.NET Code

RV here again...

From couple of weeks we have been seeing some XSS vulnerabilities in code. Today I wanted to show you guys some real world examples ranging from property assignments, data binding and JavaScript building. For each example, I will offer both the vulnerability and mitigation which is very useful in self reviews. Before I say anything further, I want to caution you by saying that the following code examples must never be used in any application.

Example #1

In this case, we are simply using the user input directly in a label. The following is the vulnerable code.


    1: string strUsername =  txtUsername.Text;
    2: string strPassword =  txtPassword.Text;
    3: if (AuthenticationClass.Authenticate(strUsername, strPassword))
    4: {
    5:     //Set auth cookie and redirect, always use FormsAuthentication.SetAuthCookie
    6: }
    7: else
    8:     lblMessage.Text = string.Format("{0} is not found, click here to register!",
    9:                      strUsername);

Line 8, the username is directly being used to output the message. The following code fixes the vulnerability.

    1: lblMessage.Text = string.Format("{0} is not found, click here to register!",
    2:                   AntiXss.HtmlEncode(strUsername))

Example #2

In this case, we are data binding data from a database.

    1: //Probably the most common code that is vulnerable to XSS
    2: //This is persistent XSS vuln, a very dangerous as one
    3: //user attacks and many users will get exploited.
    5: <asp:Repeater ID="repFeedback" runat="server" >
    6: <ItemTemplate>
    7: <p><asp:Label runat="server" ID="CommentsLabel" Text='<%# Eval("Comments") %>'/> 
    8: <br /> - <i><asp:Label runat="server" ID="NameLabel" Text='<%# Eval("Name") %>'/>
    9: (<asp:Label runat="server" ID="EmailLabel" Text='<%# Eval("Email") %>'/>)</i></p>
   10: </ItemTemplate>
   11: </asp:Repeater>

Line 7-9 are vulnerable to XSS. Fortunately there is a very simple way to fix, which is shown below.

    1: <asp:Repeater ID="repFeedback" runat="server" >
    2: <ItemTemplate>
    3: <p><asp:Label runat="server" ID="CommentsLabel" 
    4: Text='<%# AntiXss.HtmlEncode(DataBinder.Eval(Container.DataItem, Eval("Comments"))) %>'/> 
    5: <br /> - <i><asp:Label runat="server" ID="NameLabel" 
    6: Text='<%# AntiXss.HtmlEncode(DataBinder.Eval(Container.DataItem, Eval("Name"))) %>'/>
    7: (<asp:Label runat="server" ID="EmailLabel" 
    8: Text='<%# AntiXss.HtmlEncode(DataBinder.Eval(Container.DataItem, Eval("Email"))) %>'/>)
    9: </i></p>
   10: </ItemTemplate>
   11: </asp:Repeater>

Also, please note that DataBinder.Eval and Eval are slow as they use reflection to parse the expression. A better option is to use the Container.DataItem directly as it is a DataRowView object.

    1: <%#Microsoft.Security.Application.AntiXss.HtmlEncode
    2: ((((System.Data.DataRowView)Container.DataItem)["Comments"]).ToString()) %>

Example #3

In this case, we are using a ASP.NET value in the JavaScript.

    1: <script language="javascript">
    2: function showMessage() 
    3: {
    4:     var message='<%=this.strMessage%>';
    5:     var div = document.getElementById('messageLabel');
    6:     div.innerHTML=message;
    7: }
    8: </script>

Line 4 has the vulnerability. Anytime you use .NET variables or data directly into java script, that is a perfect recipe for a disaster. In fact, this vulnerability is so dangerous that neither ASP.NET Request Validation nor Server.HtmlEncode cannot protect you. Only AntiXss has native java script encoding.

    1: var message=<%=AntiXss.JavaScriptEncode(this.strMessage)%>;

Please note that AntiXss.JavaScriptEncode automatically surrounds the input with single quotes to make it a valid string.

We have seen three most common examples but there are many other vulnerable ways. The following is the small list of properties which could return untrusted input. By no means these values should be trusted, they should be validated and encoded during output.

Class name and property

Please note that there are other ways in which you can get user input and could result in a XSS attack. The best strategy is to identify user inputs and encode them before sending back to the browser.