Cross Site Scripting is the second most prevalent issue in the OWASP (Open Source Foundation for Application Security) top 10, found in roughly 2/3 of all applications. While automated tools can find some of these problems, there are also automated tools designed to detect and exploit these vulnerabilities, making it crucial that security teams identify and address the vulnerabilities first.
XSS attacks occur when data enters a web application through an untrusted source (like a web request), and is sent to a user without being validated. XSS can cause scripts to be executed in the user's browser, resulting in hijacked sessions, website defacement, and redirection of users to malicious sites. Essentially, an attacker inserts a malicious script into a section for user input (which the server expects to be data, not commands). If not appropriately handled, the malicious code can break out of the 'data plane' and execute as normal code (the 'control plane').
Reflected XSS (Impact: Moderate): This is the most basic type of XSS, wherein an application receives data and then includes that data in the response to the user in an insecure way.
For example, if an attacker convinces a user to click this phishing link:
And the legitimate site doesn't process the data before returning it to the user, the malicious code will be executed by the user's browser.
Stored XSS (Impact: Severe): Stored XSS occurs when the injection is permanently stored on the target's servers, such as a comment or message in a forum or comment section, in a database, etc. This allows the exploit to impact every visitor to the site/application.
For example, if a site allows users to comment and for their comments to be displayed, a user could enter the following:
If the site doesn't check user input appropriately, it could result in the script executing for any other user who sees this message.
DOM-based XSS/Client Side XSS (Impact: Moderate): The big difference between reflected and stored XSS and DOM-based is where the attack is injected. Reflected and stored XSS are server side issues, while DOM-based is a client (browser) side issue. DOM-based XSS occurs in the DOM (document object model) instead of as part of the HTML.
Rather than inserting malicious code into the page, this attack will allow the legitimate page to load, then leverage user input to add HTML to the page, executing the malicious script. This attack takes advantage of an increasing amount of HTML generated by the client.
For example, an attacker could social engineer a victim into clicking a malicious link (such as http://www.legitimatewebsite.com/contact#<script>malicious code</script>). The website will receive the legitimate request for the page, but not the malicious fragment (because browsers don't send anything after the # character to a site's server). The victim will see the legitimate website, but the victim's browser will also execute the malicious script.
Mitigating effectively against XSS attacks requires a combination of the below measures, which, when used together, can provide a robust defense against XSS.
Avoid inserting user-supplied/untrusted data anywhere other than specified locations: This is the first, and most important rule. Encoding, escaping, validating, and filtering input is extremely difficult and very complicated. It's much easier to limit the number of places where untrusted data can be input. The safest assumption is that all untrusted data is malicious.
Validate/Filter Input: Ideally, all input should be validated against a whitelist of acceptable values.
Choose Frameworks Carefully: Use frameworks which provide automatic escaping functionality (like Go Templates) or those which have native defenses against XSS (like .NET's request validation).
Security Education: Education specifically targeted at developers, like 'Security Champions' programs which pair application security team members with developers can educate developers about security vulnerabilities (like XSS) and how to prevent them.
Content security policy: A content security policy (CSP) can help detect and mitigate XSS and other data injection attacks. They set allowlists for sources of trusted content and can apply only to sensitive pages (like payment pages) or, ideally, to the entire site. They can even provide notifications if content is loaded from a page which it should not. They're fairly easy to deploy - just add the Content-Security-Policy HTTP header to the webpage and any directives that are appropriate. Typically a policy consists of a series of directives which will describe the policy for a type of resource or area.
One of these directives, sub-resource integrity checks, is used to ensure that a browser verifies all third party content (from sources like a CDN), was delivered without being manipulated. To do this, a provided cryptographic hash is checked against the loaded file. If a hacker modifies the third party's content, the site simply will not load the malicious content.
The CSP Fiddler Extension can help you generate a baseline CSP. The tool will build a policy around reports submitted by the browser, creating a changeable baseline policy. Additionally, Report URI, run by Troy Hunt and Scott Helme can be used to get alerts on CSP violations in order to more proactively monitor sites.