My colleagues claim that XSS is a vulnerability on the server side. I always thought that this is a client side vulnerability. Which one of us is correct, and why?
It manifests itself on the client side, but that is because it is allowed to do so by the web application. The application doesn't validate the code that it sends back to the browser. And thats why it is a server side vulnerability. Think about it this way. What would you do to fix the issue of XSS? Fix the server side code or fix the browser?
Cross-site Scripting (XSS) attacks can generally be categorized as one of:
- Stored XSS Attacks
- Reflected XSS Attacks
- DOM Based XSS Attacks
The attack itself is taking place on the client. All three attack types could fully manifest themselves in the browser itself in the case of a single page or offline application. However, if the data is stored on the server or reflected from the server, then the server is assisting in the vulnerability.
IE8 introduced X-XSS-Protection, which made reflected attacks more difficult to exploit.
The terminology is a little slippery, but usually an "XSS bug" is a client-side exploit of a server-side vulnerability.
Cross-site scripting is not, in and of itself, a security problem. The problem is that it can happen without the end user's knowledge. Most sites aren't coded for this to happen, of course: either they don't use cross-site scripting at all, or they make it clear that this is what they're doing. But if users can post their own content, then you need to keep them from adding arbitrary script tags to the pages. Otherwise, they could slip stuff into the page that sends data to who knows where.
To prevent this, you need to parse out the user-created content, and then generate "clean" HTML for display which doesn't have the tags you don't want (like script tags). Some sites use this opportunity to have users create their content in a language that isn't HTML: Stack Exchange uses Markdown. But as long as you still parse the content properly, you can use HTML as the input language too. There's no performance benefit to properly done HTML-to-HTML, since it goes through the same kind of parse/generate cycle that other languages would, but it's one less language for developers (and possibly users) to learn. You do, however, have to resist the temptation to just reuse the HTML content as-is, or to do some light string substitutions instead of a parse/generate cycle.
An "XSS bug" is what happens when people figure out how to post arbitrary HTML to the site. Usually this happens when developers directly use HTML input without going through the parse/generate cycle, but sometimes somebody finds a way to trick the site's generator into giving them HTML that it wasn't designed to give. Either way, the end result is the same: once a user can post arbitrary HTML, they can do cross-site scripting with it, and that's why we call it an XSS bug. But the bug isn't in the XSS itself: it's in the server-side code that allowed arbitrary scripts to be posted in the first place.
tl/dr: If the server is building the HTML then the server needs to protect against XSS. If the client is building the HTML then the client needs to protect against XSS.
With changes in the way web applications are built this question deserves a re-visit, since the answer is more than just a matter of semantics. The answer is actually surprisingly simple:
XSS happens wherever HTML is built!
At the time this question was asked, AngularJS and React where roughly 3 years and 1 year old (respectively). This is of note because these frameworks really helped speed the switch to client-side applications, in which HTML is not just rendered client side (as it always has been) but also constructed client side. With client side applications XSS switches from a server-side vulnerability to a client-side vulnerability. The difference is important:
Protecting against XSS
Normally you protect against XSS by escaping the appropriate control characters, depending on your context. So if you are building HTML like this:
You would convert
" (among other things). If your server-side application is returning a string of HTML to the browser, then clearly it must take care of this while generating the HTML. In many modern back-end frameworks this happens automatically in the templating systems.
However, if your server is simply returning data (perhaps via a JSON response) to a client side application running something like React or Angular, then it shouldn't do anything at all! The reason is that the client side application is the one that is going to be building the HTML, and so it will perform any necessary XSS protection. If the server escapes the HTML first, then it will end up double escaped, which means that instead of seeing this:
Welcome to Bob's Page!
The user will see this:
Welcome to Bob"s Page!
Because the full system will go through this flow:
- From the database:
- Escaped by the server and sent to the client:
- Escaped by the client application and rendered in the browser:
It is generally best practice to filter as many things as you can on the server side and not on the client size for the following reasons:
- Liability (Once you have sent out data you shouldn't have, you can not control the effects of it)
- User Safety (You generally don't know what version of your client the users have)
An XSS attack is not much different from an SQL injection. Both are caused by not controlling user input properly. XSS attacks are generally stored in your database and distributed through your system to your clients.
Hope it helped. I recommend this read for further information: https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
I've read some people who care about not using the url or whatever to load different user info or whatever (such as some here in google's tutorial - https://xss-game.appspot.com/)
While that's nice to be aware of, you gotta remember that every single function and piece of code on the client side can be arbitrarily executed. Validation and protection for XSS comes comes from the server. I mean think about it, you can open up the console itself.
The idea is the injection of malicious code from client that ends up being a vulnerability on the server. This may cause the other clients to receive web pages with crappy scripts embedded in them. Think of a forum -- if you just saved and render tags in that post someone made you could be making be arbitrarily execute code for whoever views that forum post.
For example, if stackoverflow wasn't escaped properly, you probably would have been redirected to google.com w/ the below
window.location.href = 'http://google.com' (imagine this being surrounded by script tags, SE formats them out and too lazy to escape them)
[enter preformatted text here]