Sometimes I like to describe security vulnerabilities as if they were people or characters, rather than abstract concepts. With a human face applied to them it’s a little easier for people to understand my explanation. For example, SQL injection is kind of like James Bond: He sneaks into places that he's not supposed to have access to and then escapes with all of your secrets. A buffer overflow is like Mr. Creosote from Monty Python's The Meaning of Life: He tries to cram way too much data into a space that's not meant to hold it and the results are disastrous. If Cross-Site Scripting (XSS) were a person, it would definitely be Rodney Dangerfield. XSS never gets any respect! Many people still think of XSS as just a silly vulnerability that can only be used to pop up message boxes in the victim's browser. Recently, a representative from McAfee stated that the presence of XSS on Web sites would not prevent those sites from qualifying for McAfee's "Hacker Safe" certification. I strongly disagree with this position. Just look at some of the ways XSS can be exploited:
· Session hijacking: This is a classic example of exploiting an XSS vulnerability. The attacker injects script into the vulnerable page so that visitors to that page will automatically, and silently, send their document cookies to the attacker. Depending on the site attacked, those cookies may include the user's session and authentication tokens. Once the attacker gets these tokens, he can impersonate the user on the vulnerable site, essentially committing a form of identity theft. A vulnerable email application might allow an attacker to read the victim's mail or to send new mail in the victim's name. A vulnerable banking application might allow an attacker to empty the victim's checking account into his own.
· Phishing: In a successful XSS exploit, the attacker can often alter not only the client-side script code of the vulnerable page, but the HTML, as well. This ability can be used to add new form fields of his choosing, perhaps two text-box inputs labeled "username" and "password" along with a "submit" button. Of course, the attacker will make sure that this data won't get submitted back to the legitimate Web site, but rather back to him at his evil Web site where he can use it at his leisure. This is the ultimate phishing attack since the victim really is at the legitimate Web site; it's not the typical hoax site setup, but information is being stolen, nonetheless.
· Web worms: Some persistent XSS vulnerabilities can allow attackers to create Web worms. Web worms are XSS attacks that affect not only the target user, but also spread out to affect that user's friends or contacts and, from there, to those peoples' friends or contacts, and so on. Popular targets of this kind of attack are Web-based email clients (the worm spreads through the target's contact list) and social networking sites (the worm spreads through the target's friend list or alternatively spreads to anyone who views the target's profile). Web worms can grow at an exponential rate and consume more and more resources until the server grinds to a halt and crashes.
At this point you should be thinking about XSS less like Rodney Dangerfield and more like Don Corleone: a powerful and dangerous person who deserves your respect! How can you find XSS vulnerabilities in your code and, more importantly, how can you fix them? The underlying programming error that leads to XSS vulnerabilities involves displaying user input without first correctly validating and encoding that input. If you ever echo users' input back to them (for example: "Your search for 'foo' returned 1337 results") or store users' input and display it to other users (for example, if your site includes a wiki or a message board), then that code may be vulnerable to XSS. Search out conditions like this in your source code and then ensure that this functionality is secure against XSS by encoding it with the appropriate encoding algorithm. For example, if the user input will be rendered in the page as HTML, then perform HTML encoding on the input text before that text is echoed in the response. This will cause malicious input text like ""to be encoded as ""which will render in the browser as the text "" and not be interpreted as a script command. Similarly, if the user input will be rendered in the page as a URL (for example, as the href attribute of an element), you should then apply URL encoding (and, subsequently, HTML encoding) on the input text. A complete list of possible output formats and corresponding encoding types is beyond the scope of this article, as are methods for dealing with situations where you might want to allow the user to input HTML or script. However, there are some excellent additional resources available that detail these solutions (see resources listed below).