Adopting third-party libraries to encode user input in the development phase and using a web application firewall in the deployment phase could fool web security managers into thinking their web applications are completely safe from Cross-Site Scripting (XSS) attacks. While it’s a good idea to employ these techniques, the illusion of safety could prove costly. These protection methods do not guarantee that your web applications are 100% free of XSS vulnerabilities, and XSS attacks that use more sophisticated techniques still occur, so care should still be taken.
In the past several months, Yahoo and Facebook patched two critical XSS vulnerabilities. These clearly show XSS vulnerabilities continue to occur in modern and mature web applications, even for Internet companies. The XSS vulnerability in Yahoo email was straightforward: the input validation was not robust enough to escape malicious code, and the attacker was able to break input validation. The one patched by Facebook was a little trickier because it exploited a bug in the file upload function to upload malicious JavaScript code and then invoked the code by calling it from a different application. Just this week as I was finishing this blog post, an insufficient input validation XSS vulnerability was disclosed in the popular WordPress pluginNinjaForm.
As I have observed from my work experience and as a bug bounty hunter, XSS vulnerabilities are definitely not going away — and many attacks are getting more sophisticated. The golden age of penetration testing, when pen testers could discover XSS vulnerabilities simply by inputting malicious code into a search box, is over. It often takes more skill and effort for webmasters to discover the XSS vulnerabilities they need to protect against.
XSS Hidden by Web Application Firewalls
Web application firewalls (WAFs) are commonly used to protect web applications. They are indeed effective in blocking a large number of web attacks. Some pen testers give up immediately when they determine the web application is deployed behind a web application firewall. However, a WAF is just like a cast that by itself does not fix the broken limb. And like a cast, a WAF is best used as a temporary protection until the underlying issue, in this case a coding error, is fixed and redeployed.
Instead of fixing the issue, WAFs just hide XSS vulnerabilities and makes it harder for attackers to exploit them, which is their purpose; but WAFs also makes it more difficult for penetration testers or automatic scanners to discover these vulnerabilities. According to the research, over 70% of existing WAF rulesets can be bypassed through XSS obfuscation techniques. As a rule-based tool, WAFs trap the main cases for which rules are defined, but not all of the corner cases — the development effort spent to make the perfect ruleset would be better spent fixing the underlying coding error.
Recommendation: When running a security audit, e.g. via automated tools or penetration tests, always disable your WAF so that the XSS vulnerabilities can be discovered to the greatest extent. You want to make it easy on yourself to find XSS vulnerabilities, so you can fix them in your code.
In my work, I have seen many examples where customers claimed that Qualys Web Application Scanning (WAS) had generated false positives, when in fact they were true positives but the customer didn’t see the exploit because they were protected by a WAF. In these cases, I could often exploit the XSS anyway by coding exploits that bypassed the WAF protection.
Example: Methods to bypass WAF could be found on the Internet: Using escape sequences (%00onload%00=%00) instead of regular text; or an alternative XSS method, such as, payload document.body.outerHTML=maliciouscodes could be used to break some WAFs.
More Sophisticated XSS Attacks
Three types of sophisticated XSS attacks are difficult for pen testers and tools to discover. It is not easy to propose new techniques to combat these, except enhancing security implementation during web development and employing a DAST (dynamic application security testing) tool for regular security audits to make sure you catch any that were inadvertently included in your code.
DOM-Based XSS
Attacks against DOM-Based (Direct Object Model) XSS vulnerabilities modify the client side DOM tree in the victim’s browsers and run malicious code; as opposed to a traditional XSS vulnerability which exploits the server side code. DOM-based XSS vulnerabilities are harder to detect than the traditional XSS vulnerability because they resides in the script code from the website and the injection payloads are not reflected directly in the response. It has been estimated that 30% of XSS attacks on live websites are XSS inside JavaScript code and cannot be blocked by a WAF. Due to the difficulty of discovering them, DOM-based XSS vulnerabilities become a blind spot for many scanning tools and penetration tests.
Example: Here is the normal format of a DOM-based XSS attack vector
http://www.some.site/page.html#name=<Malicious-JavaScript-Code>
Multiple Step XSS
Multiple Step XSS vulnerabilities require the user to perform several actions on the applications to execute the attack vector/injected malicious JavaScript code. The main characteristics of multiple step XSS vulnerabilities are that the attack vector is injected in one page and then echoed in another page or application later. Due to this factor, it creates a challenge for penetration tests or ordinary DAST tools to identify this kind of vulnerability.
Example: Qualys WAS reported a XSS vulnerability in a customer’s application. The customer’s security team claimed they could not find the injection point and wanted to flag it as a false positive. After investigation, we found the injection point was from a different subdomain and the malicious code was invoked by making a search with a keyword matching with the malicious code injected in the response.
Path-Based XSS
Targets for Path-Based XSS attacks are applications where the request URLs are rendered directly in the response body without proper encoding or input validation. The following source code snippet is a model demonstrating how path-based XSS vulnerabilities reside in your web applications.
<a href=" <?php echo $_SERVER['REQUEST_URI'];?>">Click Here</a>
Example: Path-Based XSS vulnerabilities are a special breed but it is not rare. I have discovered path based XSS vulnerability in PHPBB3 and some other open source web applications. Meanwhile, multiple path-based XSS vulnerabilities were flagged in our clients’ web applications. The attack vector looks like:https://example.com/public/<Malicious JavaScript Code>/directory1
Conclusion
While WAFs are a great protection measure against attacks on vulnerabilities resulting from coding errors that you have not yet fixed and deployed, you should always disable WAFs for internal testing. This helps ensure you don’t inadvertently overlook any simple XSS vulnerabilities in your code. It’s always safer to fix the underlying vulnerability than to rely on a WAF for long-term protection.
In addition, developers should take care in their coding to look for the more subtle XSS vulnerabilities, since we are regularly finding attacks that try to exploit these.