root@dafthack:~#‎ > ‎

Stored XSS via Reflected XSS... or How Not to Fix Your Web Application

posted Feb 1, 2016, 10:18 AM by Beau Bullock

This is a cross-post from the Black Hills Information Security blog. You can read it here: http://www.blackhillsinfosec.com/#!Stored-XSS-via-Reflected-XSS-or-How-Not-to-Fix-Your-Web-Application/c1592/56aa33c40cf289b6a281f44c

Cross-Site Scripting (XSS) is a vulnerability commonly found in web applications that allows attackers to inject scripts that will execute in a target’s browser. Often times these vulnerabilities are exploited to gain access to a target’s session tokens. There are a few different flavors of XSS that are known to exist. The most common form we find is Reflected XSS. Reflected XSS is typically found in form fields where the user’s input is reflected back to the browser. For example, a website that accepts a parameter via the URL itself might inform the user on the page that the parameter doesn’t exist.

A simple proof of concept link to demonstrate Reflected XSS (where <script>alert(‘This is XSS’)</script> is the injected script) would be the following:


http://targetwebsite.com/page?id=<script>alert(‘This is XSS’)</script>

If the target website and ‘id’ parameter are vulnerable to reflected XSS then upon visiting this link the injected script will be executed in the browser.
In order to execute this attack a victim must be tricked into visiting a page hosting an iframe with the link embedded within the site, like on a forum or blog site. Or the victim must be coaxed into clicking directly on a malicious link. This part can be tricky as there are some social engineering elements involved in getting the target user to visit the malicious link.

A second, more serious type of XSS is called Stored XSS. Stored XSS makes exploitation of a target much easier for an attacker. Instead of the XSS script needing to be located within a link itself the malicious script can be injected into a web application where it is then stored in a persistent state. While it is still true that a victim that an attacker wishes to target must visit the site where the XSS script is stored in order for it execute in the victim’s browser, it might not take as much work for an attacker to get them to visit it.

An example of a Stored XSS might be found in message board functionality of a site where users can post various messages to other users of a site. Typically, these messages are “stored” so they can be displayed to other users later on. If an attacker can successfully inject malicious scripts in these locations a Stored XSS vulnerability might be present.

In a recent assessment I was working on I found an interesting way to execute what is essentially a Stored XSS attack by utilizing a Reflected XSS found in another part of the site. The way I stumbled upon this technique was during the third retest of a web application I was performing for an organization. During the first two retests the organization had attempted to fix a Stored XSS vulnerability but each time I was able to evade the fixes they put in place. I will detail each of these in this post and how I ultimately was forced to find a new way to exploit the Stored XSS vulnerability, by leveraging a Reflected XSS in the same target application. Also, I’d like to detail how they “tried” to fix the vulnerability and how they failed each time.

In this post I’d like to highlight two things.
  1. What is Stored XSS via Reflected XSS
  2. How not to fix your web application
The Stored XSS vulnerability I located in this particular application was very similar to the example I laid out above. It was a message board where the users of the application could communicate messages to one another. Initially, the vulnerability could be executed by submitting a simple XSS script with onmouseover element to the message board:


<IFRAME src=# onmouseover="alert(document.cookie)"></IFRAME>

On the first retest of this application I found that it started validating the attributes ‘src’ and ‘onmouseover’. So I gave it a valid ‘src’ and modified the script to perform an "onload" instead of "onmouseover". This worked:


<IFRAME src=test.com onload="alert(document.cookie)"></IFRAME>

The fact that this worked indicated that the organization was simply patching the proof of concept I provided to them. This is not the way to fix vulnerabilities penetration testers give you.
At the end of this article I will address the mitigation side further. On the next retest they made sure I couldn't use any attributes like onload or onerror. I found that I could submit something like this and the application would accept it though:


<IFRAME src=”javascript:alert(1);”></IFRAME>
I found that even though this script was submitting successfully to the site the XSS wasn’t executing in the browser. Looking at the source code of the page that is being presented by the application it appeared that the application was appending an extra field that was preventing the XSS from loading. I was able to use the JavaScript comment characters "//" to comment that part out. Everything after the script I wanted to execute was now ignored, including the extra field that was being appended. This now worked as a stored XSS technique for the message board:

<IFRAME src="javascript:alert(1);//"></IFRAME>
Again, the organization simply was patching the proof of concept I provided them through input filtering. The true underlying issue was not being addressed. On the third retest I was having a really difficult time getting around whatever fix they put in place on the message board form. So, I tried something that I'm not sure has been highlighted much in terms of finding Stored XSS. I was able to utilize a Reflected XSS from another part of the web-app where I was able to previously inject a Stored XSS script to achieve the same result. So it's Stored XSS via Reflected XSS... I suppose.

I say “Stored XSS via Reflected XSS” but in reality it is truly just a combination of Reflected XSS and HTML injection. It was evident that the developers of the application spent time filtering the input to this message board. The problem was that HTML content could still be submitted. Even though they did a good job blocking common XSS attacks in this form I was still able to force a target’s browser to load a Reflected XSS script via an iframe that was submitted to the message board. The submission would look like this:

<IFRAME src="https://targetwebsite.com/page?id=a"><img src=a onerror=alert(document.cookie)>"></IFRAME>

Now whenever any user navigates to the message board their browser will load the iframe containing the Reflected XSS link. Since this iframe is stored within the message board it will essentially execute the same way the Stored XSS scripts executed previously.

For pentesters:

When you are performing a web application assessment in the future and you locate a form you can submit and store data to try submitting an iframe with a Reflected XSS script. You might find that you can create a Stored XSS condition when none of the standard XSS injection techniques work. Automated scanners will not detect this method of executing Stored XSS as the attack requires previous knowledge of a Reflected XSS vulnerability. When assessing mitigations put in place be thorough and don’t be afraid to try new things.

For developers:

Output encode HTML and HTML attribute contexts. This means take the untrusted user input (i.e. <script>alert(1)</script>) and convert it to HTML encoding (i.e. The less than symbol ‘<’ would convert to &lt; The greater than symbol ‘>’ would convert to &gt;). Now when the the user input is displayed back to the user it is being displayed as data rather than executable code. Filtering input is rarely the right fix for XSS and as demonstrated in this blog post these “filters” can often be bypassed with a little creativity. Input filtering can be helpful but should only a secondary mitigation control.

A good source for Cross-Site Scripting prevention techniques can be found here:
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

As a developer XSS should be addressed at the source of the application. However, there are network based tools that can assist in preventing some of these attacks. Web application firewalls (WAF) can be utilized in front of a web application to be an additional layer (think defense-in-depth) to protect against common web application vulnerabilities.

Lastly, do not simply patch the specific proof of concepts a pentester has provided you. When presented with an issue such as XSS attempt to understand the underlying issue, and develop a plan of action to eliminate this vulnerability at the source of the problem.

_________

Beau Bullock works at Black Hills Information Security and hosts Hack Naked TV, along with many other projects. Read more about Beau here.
Comments