Reflected XSS

As some of you know, I have been spending much of 2013 doing security related testing of applications (sometimes called penetration testing, or pentesting). This is a change from my usual, 20 year history of writing secure applications. I am still all about writing secure applications, and will be doing more of that in the future, but there are a lot of apps that need to be fixed.

All of the applications that I have tested this year, from fortune 100 companies to small companies that have a community web presence, have a common and very dangerous vulnerability called Reflected XSS. This is a Cross Site Scripting vulnerability that is related to content driven XSS, but has a different, and very scary, scope - values that are directly written to the user's screen from a POST or GET operation.

I could go on and on about the dangers of XSS, but I'll leave that to OWASP, and instead tell you how to avoid it.  Leave it to this: XSS is a phishing related vulnerability. It requires users to get all clicky with an email, but when it works, it gives the attacker a very easy path to application ownage.

How it works

We all know to encode output by now, but some things, like exception handling especially, escape our view. Error handling is often encapsulated in common controls (as it should be), written quickly at the start of a project. Encoding of the output is usually not handled by the control, and is rarely implemented by those using the control.

Here is an example: a simple web site that expects the user to type the right string:

 

<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
    <h3>Only type "xss" here!!</h3>
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <br />
    Answer:
    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    <br />
    <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</asp:Content>

 In the back end, I have rolled the exception management into the codebehind, just for example's sake.

 

protected void Button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (TextBox1.Text != "xss") throw new ApplicationException("The value " + TextBox1.Text + " is not correct.");
                Label1.Text = Server.HtmlEncode(TextBox1.Text) + " is correct!!";
                Label1.ForeColor = System.Drawing.Color.Black;
            }
            catch (ApplicationException ex)
            {
                Label1.Text = ex.Message;
                Label1.ForeColor = System.Drawing.Color.Red;
            }
        }

 

Now, when we type the right string, the application behaves as expected:

  

 

And when we type the wrong string, the application also behaves as expected:

 

  

That's as far as much testing takes us.  However, when we type evilstring:

 

  

That's when the problems occur. Of course, the bad actor won't just put up an alert().

 

Fixing it

Fixing the problem is very simple.  Just encode the string you are writing to the screen. The exception manager should assume that string is evil, just like it should with every other string.

protected void Button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (TextBox1.Text != "xss") throw new ApplicationException("The value " + TextBox1.Text + " is not correct.");
                Label1.Text = Server.HtmlEncode(TextBox1.Text) + " is correct!!";
                Label1.ForeColor = System.Drawing.Color.Black;
            }
            catch (ApplicationException ex)
            {
                Label1.Text = Server.HtmlEncode(ex.Message);
                Label1.ForeColor = System.Drawing.Color.Red;
            }
        }

 

My example is in .NET, which means I had to disable the AntyXSS AntiXSS library, but if you are writing in Rails, PHP or Java you aren't so lucky.  Better to be safe than sorry.  Encode that output folks!!  ENCODE IT!!

 

 

 

 

Comments (2) -

Steve Horn
4/11/2013 6:33:27 AM #

Hey Bill,
Not clear to me what the "AntyXSS" library you had to disable is?

brooks25
4/15/2013 7:12:01 PM #

What's up}well written article, and just what I wanted to find.

Comments are closed

Bill Sempf

Husband. Father. Pentester. Secure software composer. Brewer. Lockpicker. Ninja. Insurrectionist. Lumberjack. All words that have been used to describe me recently. I help people write more secure software.

profile for Bill Sempf on Stack Exchange, a network of free, community-driven Q&A sites

MonthList