February 13, 2017

Deep Dive: Cross-Site Scripting (XSS)


It's been a while since I've written up a new post, so I thought I'd start a new series where I do deep dives into common web application security topics. The thought is to cover a lot of the things you'd typically find in a bug bounty program so that others can jump into them and be successful. I'd love to hear your feedback, so please let me know what you'd like to see more of.

What even is Cross-Site Scripting (XSS)?

There's plenty of definitions floating around on the internet, and you're encouraged to do research of your own. I'm going to try to do my best to simplify the many overly technical definitions down to something straightforward. XSS is when a web server returns user-input in the web response without properly encoding/escaping it. So, you might ask, why is it bad to include user-defined input in a web response? Well, a user can include arbitrary HTML or Javascript in their input which would then get rendered back to the user. This means a malicious user can control what content another user gets rendered back to them when viewing parts of a website. Definitely a scary thought.

What is the impact of XSS?

Since we just learned that a user can control parts of a web response, what can we do from there? Well, a malicious user can take advantage of an XSS issue to do a variety of things which I'll outline below.
  • Steal / manipulate browser cookies
    • If a cookie does not specify the HTTPOnly flag, Javascript can view the contents of this cookie and then ship that data off to an attacker's server allowing the attacker to impersonate a user.
  • Perform actions on the user's behalf
    • Javascript can make arbitrary web requests, so an XSS vulnerability could send targeted web requests that perform sensitive actions on the user's behalf (since the user's session cookie is sent along in Javascript web requests). CSRF mitigation would help stop these kinds of attacks.
  • DOS a website
At the end of the day, you are limited by what Javascript can do which based on the BeEF toolkit is essentially anything at this point.

Finding an XSS Issue

There's a handful of tools out there to assist you in finding XSS issues in a website, but knowing how to find them by hand can save you when you are without tools or your engagement doesn't allow automated tooling. Some automated tools are:

In general, you are looking for a situation where user-input is being directly reflected back in the response. A web proxy is incredibly helpful in this situation, so you can see exactly what the web server is returning in every response. A few notable web proxies are:
Now what? Well, you want to see if you can sneak in special HTML characters into a response. I typically try with a strange string like < > ; " ' / 

This will give you an idea of what special characters are being properly encoded, so you can start formulating an attack. In general, you want to be able to inject your own HTML tag or complete an HTML tag and inject a new tag following. Notice in the example below, the user can control the hover text for an image, so you can inject a closing quote / angle bracket and then start your payload.


In other situations, you may be able to control a piece of Javascript in which case you also need to know what characters are being encoded in the response so that you can being formulating an attack. Notice in the example below, a website uses the redirect parameter to define a Javascript redirect. Abusing the redirect parameter allows a malicious user to take full control of the Javascript snippet.


Lastly, my favorite way to get XSS in a website is via SVG images. SVG images are a strange image format that is effectively an XML file containing image data. Fun thing though, you can also define Javascript inside of an SVG as well.

I'm sure you can see where this is going...

If you can find a website that will let you upload an SVG image (and it does NOT process the file), you can typically get free XSS. What do I mean by process the file? Well, if the site does not transform your SVG to a PNG or JPG, you are likely good to go. The only other requirement is that you can force browse to your uploaded image (In Chrome, you right click the image, and choose Open Image in New Tab). If those conditions are met, when you open your malicious image in a new tab you should have had Javascript run. Refer to the snippet below for an example SVG with embedded Javascript.


Now, I fully understand that the examples provided are incredibly basic and not terribly realistic. However, they get the general strategy down and get you thinking about how to start thinking like a malicious user. In most situations, a decent web framework is being used or mod_security will be yelling at you for being rather rude with your web requests. In this case, you always have the OWASP XSS Cheat Sheet. Brutelogic also made a wonderful cheat sheet and a tool for creating an XSS payload.

Fixing an XSS Issue

What recommendations should you make when you submit an XSS bug? Let's be honest, you are an awesome fellow if you include remediation instructions as well as detailed write-up. Resolving XSS isn't always a hard-fast rule. It really depends on a few different factors.

In most cases, encoding all output should resolve most issues. However, what about different encoding schemes? Well, if the user input is being placed in a redirect URL, you should likely URL encode it. If the user input is being placed directly into an HTML tag, you should likely HTML encode it. If by some God awful reason it's being placed into a Javascript snippet, you better Javascript escape it.

Some people like to just remove areas where user-input is being returned in the response. Sometimes this is the easiest fix if the user input does not really need to be returned in the response.

Wrapping Up

After a while, you will start to immediately notice when a website returns back your input in a response. And trust me, you will also find yourself testing special characters in that same website just to see if you should waste your time poking for an XSS issue. End of the day, testing for XSS issues is pretty straightforward when you realize there's a handful of tools and strategies to find these issues quickly.

2 comments:

The S3 Bucket Problem - The Latest Vuln to Become Popular

Yes, yes, I'm late to the party, I know. Poorly secured Amazon S3 buckets have been a thing for a while now, but recently there's...