Some simple XSS Attacks by Example
I thought that today I’d write a bit about how XSS attacks can be performed by setting up a sample site where users could try some of the exploits discussed, to better learn how to protect their own sites. I am by no means an expert, but it seems that the vast majority of web developers are painly unaware of XSS exploits to any degree, leaving many sites vulnerable.
The page I’ve set up is actually based off of another Google service. This one is free for everyone (not just public institutions) but only allows you to add an image at the top. I probed this site for vulnerabilities but am happy to say that it appears to be solid.
For this ‘lesson’ of sorts, you’ll need to use the Firefox ‘Web Developer’ Add-on. Click here to download this add-on from https://addons.mozilla.org/firefox/60/. This add-on adds a small bar to the top of your Firefox browser that will allow you to manipulate webpages that you are currently viewing in real-time. You can edit the CSS and watch what happens, highlight different elements on the page, and tons more. What we’re interested in is manipulating form fields.
One approach developers might use to protect their site from XSS attacks is by using ‘client-side’ protections. I didn’t actually know this until recently, but many limitations you put on forms can actually be removed by the user.
Take a look at the fake service I’ve added. (You’ll probably want to open it up in another browser window or tab so that you can follow along.) Basically, the service will allow you to “customize” a page hosted on my server (I don’t actually host any customizations, in this case), much like Google’s other search service. The form will allow you to specify an image, its orientation, and its width. We’ll look at how vulnerable this application is, and what we can do to fix it.

First, look at the ‘Image’ text field. Your first thought when seeing a text field like this is first of all, if the results that you type in the field will be displayed back to you at some point and secondly, if HTML characters (particularly > and <) are properly escaped. In this case, you will note that the text you enter for ‘Image’ is directly added to to the <img> tag on the preview page, and that the > and < characters are not properly escaped. Cut and paste the following into the ‘Image’ field and click Submit.
See how it works? We provide the image that is expected, end the <img> tag ourself, and then add our script. The developer, trusting of the users, assume that only valid images will be used. Woops.
Ignore any ‘width’ or other text you see on the screen. What’s important is that you should see a Javascript alert box (assuming you have Javascript enabled). Many people who aren’t familiar with XSS attacks might be thinking “so what?”. If you can cause an alert box to appear, you can pretty much do what you want. Steal user cookies, modify the DOM, launch phishing attacks, it’s all fair game.

Next we’ll use the Firefox Web-Developer Add-on to attack the Select box on the page. Select boxes give a false sense of security — it makes it seem like the user can only be pick from certain ’safe’ options. Not true! The web-developer add-on allows you to turn any select element on the page into a text box. Interesting huh? Convert the <select> box to a text field, then copy and paste the following code in the orientation field:
Well, look at that. We thought we were limiting a users choices, but they can still enter whatever they want. The moral of this story, as said before, is you must validate EVERYTHING including things that are supposed to be trusted. In this case, one possible way to protect this orientation field would to have a few lines of code to make sure that the orientation is in a list that you predetermine (e.g., left and center). If the value of the field in the POST is not one of the values you specified as valid, omit it completely.

Finally, we’ll look at how you can similarly ignore maximum length constraints on text fields in order to exploit them more easily. The Web Developer add-on will help us here again. Click the ‘Forms’ label, then go down to ‘Remove Maximum Lengths’. This probably isn’t particularly common, but if a naive web developer thought that by limiting a field size, they did not leave enough space for you to launch any sort of attack, they made a big mistake as you can see! With the maximum limit removed, enter the following into the width field:
In summary, we saw the following vulnerabilities:
- Image field: No real protection at all; developer assumes user will input a valid image name. Could be fixed by some how checking that the image actually resolves to be an image. Another possibility would be to use a regular expression technique to make sure the path to the image makes sense. No matter the solution, using a function to properly escape HTML characters is a must. In PHP, you can use the function ‘htmlentities. (PHP.net). There are also many good PHP frameworks to help you ‘Sanitize’ your data — I like CakePHP. (cakephp.org)
- The Orientation field: A select box makes it seem like we have nothing to worry about. The user can only choose from specific options. As we saw, you have to assume anything can come out of that box. A good solution would be to predefine a small number of options, and check to make sure that what you receive from the POST matches one of your predefined variables exactly. No other checking or sanitation should be required.
- The Width field: Similar to the <select> box; you can’t rely on client side protections such as maximum field lengths to protect the integrity of your data. The value of ‘width’ should be checked server side — first, it should be 4 characters or less, and should be numeric. If anything else is received from POST, it should be discarded.
As you can see from the above examples, there are many ways in which a site can be vulnerable to XSS attacks. Looking for vulnerabilities is certainly not hard; it simply requires a certain mindset. You should constantly be thinking about how you can ‘break’ a website, force it into an unspecified state, etc… If you do find something big, make sure to report it responsibly to the owners of the site before doing anything crazy
September 25th, 2006 at 6:09 am
the ideas mentioned here are very similar to to SQL injection techniques, just substitute JavaScript for SQL. The bottom line is that all user input needs to be sanitized and checked.
So - any suggestions for a ’secure’ site that doesn’t severely limit use experience? I used to have a LiveJournal blog until I got fed up with them turning everything off, and just installed my own WordPress.
(Btw, Opera browser also allows one to edit page’s contents and reload it from cache, just not as graphical as Firefox’s plugin)
September 25th, 2006 at 8:34 am
Basically all client side validations are useless, we can override them with ease. Either by modifying the page content using javascript, or by writing a program that does a direct POST to the form processor. All error processing needs to be shifted to server side, if you really wan’t a ’secure’ site. Client side validation is only to improve user experience. That is where AJAX can come to help, doing realtime validation without page reloads, yet doing it on the server side. Also we should check for %XX characters in the fields. If ‘’ is blocked, some hackers may get around using %3C or %3E.
September 27th, 2006 at 8:17 pm
[…] Having been stressing online forms of my fellow developers at work, and reading Eric Farraro’s posts on Cross Site Scripting and his recent Google exploit, I figured just how important user input validation is, and the need to emphasise that. […]
September 28th, 2006 at 4:16 am
As Vijay says, you must perform all validation and sanitization on the server side, even if you (think) you’ve already done it on the client.
Every programmer should know the three golden rules for programming on the web:
Rule 1: Never trust the client.
Rule 2: Never trust the client.
Rule 3: Never trust the client.
December 12th, 2006 at 4:19 pm
Not sure inserting javascript (client side code) into the html is the best example of the security issues on this but I guess the point is made.