Background
As per
wiki
Cross-site scripting (XSS) is a type of computer security vulnerability typically found in web applications. XSS enables attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy.
We will see this in details as to how web applications can be vulnerable to an XSS attack and how can it be safeguarded. This is the most common known security vulnerability. You can use 3rd party produces like
IBM App scan to check for security vulnerabilities in your web applications.
Types of XSS attacks
There are many variants of XSS attacks but the major ones are -
- Reflected or Non persistent XSS attack
- Stored or persistent XSS attack
Reflected or Non persistent XSS attack
Out of this reflected is most common. In this type if xss malicious script is executed on clients browser and sensitive data might be stolen.
For eg. lets take a search field on some social networking site. You generally type is words their to either search for a particular word in your feed or to search your friend/family members. When you do this in the resultant page you see something like - "Search result for - your search query". Now if your social networking site is not safeguarded from xss attacks, attacker might inject a malicious script in the search query that will get executed when you do a search which will result in the attacker stealing your data. Worst case your authorization cookie is stolen and your account is compromised.
As stated in Wiki - A reflected attack is typically delivered via email or a neutral web
site. The bait is an innocent-looking URL, pointing to a trusted site
but containing the XSS vector. If the trusted site is vulnerable to the
vector, clicking the link can cause the victim's browser to execute the
injected script.
So when you get that mail again saying hey please review these bull**** documents please do not click it. It's either a spam or worst - attempt to steal your sensitive data, since you are logged into multiple sites with active sessions. Always see who is it sent from? Do you know that person? Does the link look suspicious? No one will give you money just like that or you will not be selected for a lucky draw without applying for it :). If you are curious as to what it actually is then copy the link and open it in incognito mode which have no active sessions or logins. Now if it asks you to login it's time to turn around.
Now what do we mean by innocent-looking URL? The URL is infact that for a trusted website. All attacker will do is inject an XSS vector in one of the request parameters. Say search parameter like in example above. He will also encode script tags and other characters so that the victim user will not be able to guess it's the affected URL. Anyway well soon see a real example of this with working code and the fix. Now lets see persistent xss.
Stored or persistent XSS attack
This is even worst that then the reflected one because this xss attack vector is stored on websites server (perhaps in it's persistent DB) and it will get executed every time user navigates to the section that uses this xss affected code. Lets see an example.
Consider a forum used to discuss programming related QnA. Again if the site is not safeguarded against XSS attacks then an attacker can ask a question which seems normal and legit but at the end contains a malicious script/attack vector. Now when he publishes the question it gets stored in the sites persistent storage and when any user tries to visit this question this malicious script will get executed on his/her browser and again your sensitive data can be stolen.
It's not always about the victims sensitive data though. An attacker can use XSS attack to permanently change the websites appearance or change display texts. Consider the damage it can do. For eg. attacker can change the announcement made by a reputed company which can result in it's stock prices crashing.
Enough with the theory let's see a practical example -
Testing for XSS
Code for this demo is available on my git repository -
It's a web app. So you can download it and run it in a web server like apache tomcat. For this demo I will use my local setup.
NOTE : This web project has multiple workflows. The files you are interested in are -
This demo also assumes you are familiar with webapps, JSP, Java, Spring etc. I have written multiple posts on these topics in the past. You can search those in this blog if you are interested.You can find everything starting from configuring and using ivy dependency management to developing sample Spring application to deploying apps on tomcat. Above web app uses all these.
Once you have deployed the web app you can open it in your browser. It should look like following -
You can add normal text in the search box and do a "Search" or a "Search Xss Protect". Everything should work fine. For eg. when I input - "I am groot!", it just shows me the query I have input -
Now lets do "Search Again" and perform a normal "Search". But this time we will search differently. Enter following query in the search box -
- I am groot!<script>alert(10)</script>
The result is -
As you can see we do see our normal result but we also see a prompt with 10 in it. Now if you revisit our input query we added a script tag at the end and the browser executed it. This was just for the demo, attackers script will execute silently in the background without prompts and steal/modify your data.
Now lets repeat the same search with text -
- I am groot!<script>alert(10)</script>
Only this time you press "Search Xss Protect". What do you see?
What happened here? No prompts? That's because we escaped out input so that it is not harmful which is exactly what the fix is. You need to escape your user inputs so that they are not executed by your browser as scripts. Now that you have seen a demo of how XSS behaves and how you could safeguard it lets see how it actually works from code perspective.
Code working
You need to revisit the JSP file -
The main culprit line here is -
This essentially evaluates the query from Java. If this has script tags those will be evaluated too. What do we do? We escape it before this line is reached which is precisely what the code does when you press protected search -
String xssProtect = request.getParameter("xssProtect");
if(xssProtect != null && xssProtect.equalsIgnoreCase("yes")) {
query = ESAPI.encoder().encodeForJavaScript(query);
}
NOTE : xssProtect is something I have internally used to differentiate between normal search and protected search for demo purposes. You need not worry about it. In production you should never have a normal search like scenario.
NOTE : ESAPI is a library that OWASP (Open Web Application Security Project) recommends. You can see a bunch of links in the related links section below. But you can technically use any library that escapes html like coverity security lib.
NOTE : Above was an example of reflected or non persistent XSS attack. What if we were storing this search queries in our internal DB and showing search history for a user? In that case it would be a persistent XSS attack.
Though above demo was a means to show you how XSS actually works and how it can be safeguarded you should never code it this way. JSP should never have such logic. All of this should be in backend logic possibly your servlets and controllers.
Related Links