As a security researcher, I regularly come across software vulnerabilities. Some can have a deep and lasting effect on the way customers and clients view the security of the organization and some can have a fairly minimal impact. However, when there are applications susceptible to a few basic types of attacks, I struggle to understand how these can continue to slip through each phase of development and into production. Frankly these types of vulnerabilities are simply irresponsible and dangerous to the end users.
There are a handful of vulnerabilities that fit into this group; cross-site scripting (XSS) being one of them – and we find them in just about every application we test. An XSS vulnerability allows an attacker to modify a web page however they see fit, sometimes by injecting javascript, flash objects, HTML or anything else the browser can render.
Because the payload is delivered by a vulnerable site, XSS will prey on a user’s trust relationship with the website they are visiting. This increases the likelihood a victim user will allow malicious code to run or software to be installed. The attack targets your application’s users and not the application itself, but it uses your application as the vehicle for the attack. Essentially, the browser has no way of discerning if the code was created by the original developer or a malicious attacker because that script is usually downloaded or at least referenced from a trusted site.
If an attacker can get an XSS foothold into the victim’s browser they can access and do anything the browser can access or do. I’ll let that sink in for a second. Think about what we do in a browser nowadays, almost everything. XSS opens the door for direct data theft, through cookies and other site information or indirect data theft through phishing and other attacks.
Anything with a web interface is potentially vulnerable. We’ve seen XSS issues in mobile devices and desktop applications. Really anything that can render HTML. Primarily though, web applications fall victim to this type of attack. When the script is stored in a database it becomes persistent, which is far worse because the same attack can be used for any user that browses to the site.
Web applications often echo user input back to them without altering it. Search engines are a good example of this type of behavior. Attackers can create and distribute URLs that contain a malicious script that gets reflected back to the user, this is, aptly named, “reflected XSS”. The most common example of this is the “page not found” error page which echoes the requested page back to the user.
What You Need to Know About XSS
Here are a few aspects of XSS attacks that your organization should be aware of relative to the impact of such an attack, but also which components and conditions that might enable XSS methods to exploit systems.
- Confidential Information Disclosure – The most common attack performed with cross-site scripting involves the disclosure of information stored in user cookies or on the page itself.
- User Exposure – Even if an attacker cannot obtain the plaintext credentials of a user, they can act as that user by stealing session IDs.
There are a number of common mistakes organizations make that leave their applications vulnerable to attack. Some of these mistakes are enormously easy to rectify, while others might not seem so obvious.
- Failure to use whitelist validation before it is processed by the application.
- Trusting data retrieved from any database or other data resource
- Failing to encode any remotely provided data, including reverse DNS lookup, cookie contents, uploaded files, etc.
- Improperly converting “safe” tags to HTML.
- Displaying user input directly without encoding it appropriately for the context in which it is used.
- Checking user submitted data against a blacklist instead of a whitelist.
Input Validation is the Key to Protecting your Organization
XSS flaws might not be easy to identify, but are easy to remove from a web application. A security code review might be the best way to find flaws and search for all places where input from a user can make its way into the HTML output.
Many different HTML tags can be used to transmit a malicious JavaScript. Automated Web Scanning tools can help scan a website for these flaws, but can only scratch the surface. If one part of a website is vulnerable, there is a high likelihood that there are other problems as well.
There are a number of considerations when taking precautionary steps against this flaw, including what language your apps are written in and what your environment looks like. Here are some best practices as to how you’d remediate:
- Perform context sensitive encoding of untrusted input before it is echoed back to a browser by using an encoding library. Most of these libraries only convert the symbols “, &, <, and > to safe HTML equivalents, however a better option is to use an encoding library that will encode all characters except a trusted whitelist:
- Python: cgi.escape (only escapes 3 characters by default, escaping ” is optional)
- ASP.NET: HttpUtility.HtmlEncode and HttpUtility.UrlEncode (only encodes 4 characters) Microsoft’s Web Protection Library is a better option here.
- Perl: HTML::Entities::encode (only escapes 4 characters by default, but it makes it easy to specify other unsafe characters).
- PHP: htmlentities and urlencode (only escapes 4 characters by default, and can optionally encode ‘ (single quote).
- Ruby: Rails has this built in with the ‘h’ or ‘html_escape’ methods.
- Untrusted input should be validated against an inclusion list before use. For example, use a regular expression to define acceptable character sequences and use it as a filter. If the input is meant to be a primitive type it can be cast appropriately to assure that it is the expected type (a type constraint) and then checked to ensure it’s in appropriate range (a range constraint).
- In the case where there are only a limited number of acceptable inputs, then the input can be constrained to that set with simple if or switch control structures, or by matching against a fixed list of strings (a domain constraint).
Summary
XSS is just one way attackers are able to penetrate corporate systems from the application level. It’s critical that organizations take the necessary steps to protect their sensitive information by ensuring that the applications they are deploying are written securely.
Input validation ensures the application processes the data that the developers know it can handle. Input validation is absolutely critical to application security, especially where most application risks involve tainted input at some level. Most applications do not plan input validation, and leave it up to the individual developers, which can derail the security that gets built into the application.
If you are able to identify that your applications are susceptible to an XSS attack, the right amount of education, training and tooling can help you resolve this issue quickly. Additionally, if you can remediate those vulnerabilities in your Web applications early in the SDLC, you’ll save significant time and money later if an attacker penetrates that application.
Joe Basirico heads up Security Innovation’s industry-recognized research team. The team performs high-level, comprehensive software assessments for Fortune 1000 organizations and large government agencies. Joe can be reached at jbasirico@securityinnovation.com and is on Twitter: @joespikey