You are on page 1of 6

Lab – Cross Site Scripting (XSS)

Objectives

After completing this lab, you should be able to:

 Recognize XSS vulnerabilities


 Encode untrusted output with HtmlEncode
 Validate input with a regular expression
 Use ASP.NET’s built-in XSS protection mechanism

Overview

Cross Site Scripting (XSS) is one of the most prevalent vulnerabilities in modern web
apps, simply because it’s so easy to overlook, and sometimes can be very subtle. In this
lab, you’ll find, exploit, and then fix two different kinds of XSS vulnerabilities.

Scenario

In this scenario, you have a web application that supports both anonymous and
authenticated users, the latter of which are authenticated using ASP.NET Forms logon.
The application is a message board which allows any user to post a message that all
others can read.

Setup

Open the before\XSSWeb.sln solution. This includes a skeletal application where you
will do your work. There is also a fully completed lab in the after\ directory that you can
use to compare with your work if you get stuck.

You’ll need to set up a virtual directory for this lab. In the before\ directory you’ll find a
program called installvdirs.exe. Run that program (it requires admin privileges to
function properly). It will create a vdir at http://localhost/FabrikamXSS. If you want to
clean up after the lab, you can run the corresponding uninstallvdirs.exe.

Effective exploits are difficult to write. Multi-browser exploits are even harder. This
particular lab was designed to work well with Internet Explorer, so even if you normally
use a different browser, please use Internet Explorer when working this lab.
Lab – Cross Site Scripting (XSS)

Experiencing and Fixing XSS Vulnerabilities

1. Familiarize yourself with the application.


a. There are three forms. The first allows you to post messages to Fabrikam’s
bulletin board. The second allows you to view messages, and the final
page is a simple error reporting page. All of these pages are designed with
ASP.NET 2.0 master pages so that you can log in or log out wherever you
are on the site.
b. Have a look at web.config. Note that the application uses Forms
authentication. The implementation for this lab is minimal; it supports two
hardcoded users, whose credentials are shown below1.

User name Password


Alice password
Bob password

c. Note the line in web.config that disables page request validation. This is
an important ASP.NET feature that helps prevent some XSS exploits, but
it’s not perfect and you should never rely upon on it for your sole
protection.2 At the end of the lab you will enable it again (so you can see
exactly what it does) just like you would in a production application. Do
your penetration testing without it, but don’t forget to turn it back on when
you go live.

2. Log in as Alice and post a benign message.


a. Use Internet Explorer and surf to
http://localhost/FabrikamXSS/PostMessage.aspx
b. Log in as Alice.
c. Type in any message you like (do not include HTML in this message –
this is supposed to be benign).
d. Press the button to submit the post. You should be redirected to the
ViewMessages page where your message will be shown.
e. Log out.

Note: Each message is stored in a text file named with a GUID. You’ll see this
implementation shortly when you look more closely at the source code for
PostMessage.aspx.

1
The passwords used here as well as the authentication mechanism are purposely simple because this is a
lab – obviously we don’t recommend using such lousy passwords in the real world!
2
There has been at least one public and successful exploit in the past that allowed the bad guys to get
around this protection mechanism.
Lab – Cross Site Scripting (XSS)

3. Put on your black hat and post a malicious message.


a. Surf back to http://localhost/FabrikamXSS/PostMessage.aspx and make
sure you’re logged out (we’re simulating an anonymous user attacking the
system).
b. Copy the following message, and post it. You might be tempted, but don’t
interact with it just yet – you’re still in the attacker’s shoes.
<h2>Wow, this site has a nasty XSS vulnerability!</h2>
<input type='button' value='Click me for a laugh!'
onclick='changePersonality()'/>
<h2>I wonder if I can see your cookie with this script?</h2>
<input type='button' value='Click to see your cookie!'
onclick='alert(document.cookie)'/>
<h2>Hey, would you post your cookie to my website please?</h2>
<input type='button' value='Click to POST your cookie!'
onclick='alert("Just kidding, but keep in mind that a real attacker
would not ask before doing this!")'/>
<script>
function changePersonality() {
var image = document.images[0]
if (image.src.match('google')) {
// switch back to Fabrikam
image.src = 'art/Fabrikam.gif';
}
else {
// switch to Google
image.src = 'http://www.google.com/intl/en/images/logo.gif';
}
}
</script>

Note: This message was carefully crafted by an attacker who simply studied the
ViewMessages.aspx page where his message will be displayed after it’s posted.

4. Log in as Alice and view the malicious message.


a. You’ll now play the part of a legitimate user. Log in as Alice.
b. Read the attacker’s message and push some of the buttons. Keep in mind
that a real attacker would not make his post so obvious – he’d simply grab
your logon cookie and quietly post it to his own web server for later use.
c. Look closely at the source of the message you posted and you can see
where the “magic” comes from. The attacker is now in complete control of
this web page. He can make it look however he likes, and he can run
arbitrary scripts on the client’s machine that look like they came from
Fabrikam (thus the term “cross-site scripting”).
d. The fact that the attacker can steal your Alice’s login cookie means he can
impersonate her. And SSL will not stop this attack!

Note: Some experts classify this as “persistent” XSS vulnerability, because the malicious
HTML is stored on disk and replayed over and over by the website. This is a very nasty
attack, as it affects all users who view messages at Fabrikam. By simply visiting the page,
a legitimate user of this website will be immediately exposed to attack.
Lab – Cross Site Scripting (XSS)

5. Fix the problem by using HtmlEncode.


a. View the code for ViewMessages.aspx.
b. Note that in Page_Load, databinding is used.
c. In the readMessages() method, find the line that reads the text of the
message, and wrap it with a call to HtmlEncode:
string text = Server.HtmlEncode(r.ReadToEnd());
d. Build the solution and browse to ViewMessages.aspx again. The message
from the bad guy won’t be pretty, but it also won’t be dangerous anymore!

6. Add another fix by validating the input.


a. Encoding output is a great first step, but blocking malformed input in the
first place is another countermeasure you should apply. View the code for
PostMessage.aspx and have a look at how each post is handled as it’s
submitted:
i. The text is gathered from the input field.
ii. The user name is discovered (we’re using Forms authentication).
iii. A text file with a unique name is created in the App_Data directory
containing the user’s name and the text of the message.
b. Add the following code right after extracting the text from the control. It
validates the incoming text and will prevent messages with HTML from
getting through. (In practice, you’ll need to fine-tune such a pattern based
on what type of data you expect users to submit.)
// filter the input using a whitelist - look for what is good!
string pattern = @"^[-\s\w\d.,!@#%&?*()+=|{}[\]:;/^$\\""']*$";
if (!Regex.IsMatch(text, pattern, RegexOptions.Multiline)) {
string errorMessage = "Your post has one or more disallowed "
+ "characters (no HTML, please).";
Response.Redirect(@"~\error.aspx?msg=" +
Server.UrlEncode(errorMessage));
return;
}
c. Log out.
d. Try posting the evil message again. It should fail and redirect you to a
page that shows an error message (Error.aspx).

7. Examine the source code for the Error.aspx page. There is a subtle XSS
vulnerability here.
a. Do you see the problem? Part of the query string is being copied directly
into the HTML output for this page. Echoing untrusted user input into an
HTML stream leads to XSS vulnerabilities.

Note: If we classified the last XSS vulnerability as “persistent”, then this would be an
ephemeral one. Because the vulnerable page simply echoes the query string in its output,
to exploit it the attacker constructs a malicious link containing a query string with an
embedded script. If he can convince a legitimate Fabrikam user to click his link, that user
will be vulnerable. The most common delivery vehicle is the phishing email, where the
attacker sends out a convincing email to Fabrikam’s customers, offering carefully crafted
links to the vulnerable web page.
Lab – Cross Site Scripting (XSS)

8. Simulate a phishing attack to exploit the Error.aspx XSS vulnerability.


a. Be sure you’re logged out of Fabrikam before you start. This attack
assumes that most users are logged out most of the time.
b. Use Internet Explorer to open the phishing_email.htm file from the root of
the XSS lab directory. If IE blocks the active content in the document,
right-click the information bar and choose Allow Blocked Content, then
confirm your decision. This is an email from a trusted company
(Fabrikam), right? 
c. Pretend you’re Alice and this is the body of an email that appears to come
from Fabrikam. It looks authentic (in fact it looks a lot like Fabrikam’s
website). Read it. It even close to being grammatically correct.
d. Click any of the links to “register for your gift” and activate the attack.
e. The link should take you to the legitimate Fabrikam website. Look closely
at the page. This is the Error.aspx page, but an average user wouldn’t
notice that. The attacker’s script dynamically replaced the text that used to
say “Fabrikam Error Page”, and “We’re sorry, but an error occurred.” with
the words “Loyalty Gift”, making it seem as though this is a different page
entirely.
f. Read the attacker’s instructions and follow them, logging in as Alice.
Read the resulting message.
g. The attacker replaced the click handler for the Log In event with code that
grabs the user name and password from the login control.

Note: If this were real attack, the script would likely post this data to a different website
under the attacker’s control. This script simply shows you that it has indeed accessed
your user name and password and can do with them as it pleases.

9. Fix Error.aspx by encoding the output.


a. Open the source code for Error.aspx and HtmlEncode the text before
assigning it to the message control:
message.Text = Server.HtmlEncode(Request.QueryString["msg"]);
b. Build the website and go back to the phishing email. Click the link again
and verify that the attack has been foiled. Note that the error page looks
like an error page again.

10. Enable ASP.NET XSS protection and try both exploits again.
a. In web.config, change the page’s validateRequest setting from false to
true.

Note: You’ve just returned to ASP.NET’s default setting, and from now on, query strings
and form fields will be checked for dangerous characters that could represent an XSS
attack. This feature has never been perfect, which is why we asked you to turn it off while
securing the application, but turning back on is a fantastic defense-in-depth measure.

b. Build the application and try the phishing attack once more. In this
particular case, ASP.NET catches the danger before your code even runs.
c. Try posting an HTML message. You should see the same thing.
Lab – Cross Site Scripting (XSS)

Conclusion

Does HtmlEncode always protect you? Keep in mind that it only encodes a few
characters, such as greater-than (<). But what would happen if you were already in a
<script> tag and you happened to be concatenating some user input while in that context?
An attacker who knows that he’s already in a <script> tag doesn’t need to use any angle
brackets in his attack. He can simply terminate the string you’re emitting into your script
and begin writing his own script statements, similar to a SQL injection attack. Be very
cautious about injecting any untrusted input into your HTML streams. And be sure to
consider the context – HtmlEncode may not be enough!

In this lab you’ve seen three ways to protect against Cross Site Scripting (XSS) attacks.
You’ve learned to encode any untrusted data before injecting it in your HTML stream.
You’ve learned to validate input as it comes in. And finally, you’ve learned how to
enable ASP.NET page validation, but you’re (hopefully) not going to rely on it as your
sole protection mechanism.

Resources

 Patterns & Practices Security Guidance


 How To: Prevent Cross-Site Scripting in ASP.NET
 Writing Secure Code, 2cnd Edition, Howard & LeBlanc

You might also like