October 27, 2015

Handling Software Vulnerabilities, Part II

This is the second part of a three-part blog series on how to handle certain software vulnerabilities. In the first part, I introduced you to the world of software vulnerabilities, their impact on the system, and the importance of keeping a web application secured. I explained one of the most notorious and widespread attacks—the injection attack—and some workarounds to mitigate these attacks. In this part, we’ll go through both cross-site scripting (XSS) attacks and cross-site request forgery (CSRF) attacks.

#2 Cross-site scripting

What is cross-site scripting?

Cross-site scripting is an attack in which a user is tricked into executing code from an attacker’s site in the context of your website. This attack happens when an attacker injects a snippet of JavaScript into your application. This JavaScript is then executed by the browser when a user visits the target page. A typical web-based application consists of many flaws, which allow a web application to print user input onto a web page without sanitizing it. There are 3 primary types of XSS:

  1. Reflect XSS: This happens when an attacker sends a link to the target web application through email, social media, etc. This link has a script embedded within it, which executes itself when a user clicks the link.
  2. Stored XSS: This happens when the injected code permanently makes its way to the target application’s memory, such as through the database, a message in a forum, or a comment. The victim then gets the same malicious script from the server when it requests the stored information, and the malicious script is executed by the browser because it is coming from the same web application and is trusted by the browser.
  3. DOM-based XSS: In this type of attack, no HTTP request is required; instead, the script is injected by modifying the DOM of the target site in the client site code, which is in the victim’s browser, and then executed.

What are the risks?

Below are some of the potential risks of cross-site scripting:

  • Retrieval of data from the target web application
  • Modification of contents on the target page
  • Redirect victim to some other malicious or spoof page
  • Creation of a platform to install other malware on victim’s system

The consequences of any of these can seriously impact the ability of a web application, their customers, and reputation of their organization.

Below is an example of reflected cross site scripting:

In this kind of attack, an attacker tries to inject script to the server and let it come back to the browser to make it run. In the screen shot below, the attacker has entered a potentially dangerous script into a user input field.

Software Vulnerabilities

Upon clicking the “Submit” button, the script is executed by the browser.

software vulnerabilities

How can it be fixed?

The fundamental source of cross-site scripting is the acceptance of invalidated values as an input from users. There are two major fixes for this:

  1. Input validation: this simply means validating all the inputs from a user before using them. All the input characters are validated against a white list of characters, which can look like a field on the web page for contact numbers only accepting numeric values as an input.
  2. Output encoding: this means encoding or escaping the potentially dangerous characters before using them as an output on a web page. This means that even if some of the input values had any control characters within them, those will not be treated as control characters by the browser, and any unwanted script won’t be executed.

For more information on XSS attacks, please visit here.

#3 Cross-Site Request Forgery (CSRF)

This is a vulnerability that makes it possible for an attacker to force a user to unknowingly perform an action. This can happen if a user logs into a site that they use a lot (such as their email, Facebook, etc.), and then visits a malicious site without first logging out. If the original site is susceptible to a CSRF attack, then the malicious site can do evil things on the user’s behalf. Common targets for CSRF include cloud storage, social media, banking, and online shopping applications because of the wealth of user information and actions available in these applications. Approximately 23% of all applications tested are vulnerable to CSRF.

What are the risks?

Depending upon the action being performed by a user, a CSRF vulnerability can have serious consequences for a user using the web application. The main issue with this is that users are typically not aware that an attacker is performing malicious actions, all the while changes have been logged in the name of the user without their knowledge or permission. Common outcomes of CSRF by an attacker can range from embarrassing social media posts to money being stolen from a bank account.

How can it be fixed?

There are many ways to prevent your site from CSRF. While these methods do not allow absolute freedom in putting untrusted data into an HTML document, they should cover the vast majority of common use cases. You are not supposed to implement all of these methods to counter CSRF attacks, only those that qualify for you. Here are some of the most effective methods to counter CSRF:

  1. Deny all: The first and most effective way to counter CSRF attacks is to not allow any untrusted user-supplied values in your HTML document. Most importantly, never accept actual JavaScript code from an untrusted source wanting to execute it. Escaping special characters as a way to counter CSRF is not a guaranteed solution because there are so many strange contexts within HTML and escaping rules get very complicated. This includes “nested contexts” like a URL inside a JavaScript. The encoding rules for those locations are tricky and dangerous. Below are some of the sample places where you shouldn’t put untrusted data:
    <script>...NEVER PUT UNTRUSTED DATA HERE...</script> 
     <!--...NEVER PUT UNTRUSTED DATA HERE...-->             
     <div ...NEVER PUT UNTRUSTED DATA HERE...=test />       
     <NEVER PUT UNTRUSTED DATA HERE... href="/test" />   
     <style>...NEVER PUT UNTRUSTED DATA HERE...</style>
  2. HTML Escaping: If you want to put untrusted data directly into the HTML body somewhere then always perform character escaping before doing that. The escaping fix is applicable to the following contexts only:

    Escape the following characters with an HTML entity encoding to prevent switching into any execution context, such as script, style, or event handlers. Using hex entities is recommended in the spec.

     & --> &amp;
     < --> &lt;
     > --> &gt;
     " --> &quot;
     ' --> '     ' not recommended because its not in the HTML spec (See: section 24.4.1) ' is in the XML and XHTML specs.
     / --> /     forward slash is included as it helps end an HTML entity

     Please refer to the ESAPI reference implementation of HTML entity escaping and unescaping here.

  3. Attribute escaping: This applies to the case when you decide to implement untrusted data into typical attribute values like width, name, value, etc. This doesn’t apply to complex attributes such as href, src, style, or any of the event handlers like onmouseover. For event handlers, there is a different escaping theme to counterattack. Except for alphanumeric characters, escape all characters with ASCII values less than 256 with the &#xHH: format to prevent the attributes from switching. This solution works only for quoted attributes because unquoted attributes can be broken out of with many characters, including [space]%*+,-/;<=>^ and |.
    <div attr=...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...>content</div>     inside Unquoted attribute
     <div attr='...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...'>content</div>   inside single quoted attribute
     <div attr="...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...">content</div>   inside double quoted attribute
  4. JavaScript escaping: The only safe place to put untrusted data into the code is inside a quoted “data value.” Including untrusted data inside any other JavaScript context is quite dangerous, because it is extremely easy to switch into an execution context with characters, including (but not limited to) semi-colon, equals, space, plus, and many more. These should be used with caution.
     <script>alert('...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...')</script>     inside a quoted string
     <script>x='...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...'</script>          one side of a quoted expression
     <div onmouseover="x='...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...'"</div>  inside quoted event handler

    Remember, there are some JavaScript functions that can never safely use untrusted data as input, even if JavaScript is escaped. For example:


    An extension to this rule deals with JSON data. In a Web 2.0 world, the need for having data dynamically generated by an application in a JavaScript context is common. Often, an initial block of JSON is loaded into the page to act as a single place to store multiple values. This data is tricky, though not impossible to escape correctly without breaking the format and content of values. The simplest way to escape JSON directly in JavaScript is to normalize the JSON server-side by converting ‘<’ to ‘\u003c’ before delivering it to the browser.

  5. CSS escaping: This applies to the cases where you put untrusted data into a stylesheet or a style tag. CSS is very powerful and often the most ignored piece of code, even though it is prone to numerous attacks. Thus, it’s important that you only put untrusted data into a property value and nowhere else. You should avoid putting untrusted data into complex properties like url, behavior and custom.
    <style>selector { property : ...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...; } </style>     property value
    <style>selector { property : "...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE..."; } </style>   property value
    <span style="property : ...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...">text</span>       property value

    Just like JavaScript context, there are some CSS contexts that can never safely use untrusted data as input, even if they have been properly CSS escaped. You will have to ensure that the URLs only start with “http,” not “javascript,” and that these properties never start with “expression.” For example:

    { background-url : "javascript:alert(1)"; }  // and all other URLs
    { text-size: "expression(alert('XSS'))"; }   // only in IE
  6. Security encoding library: Microsoft provides an encoding library named the Microsoft anti-cross-site scripting library for the .Net platform. Additionally, ASP.net has a built-in ‘ValidateRequest’ function that provides limited sanitization. Similarly, there is a high-performance encoding library for Java that can be found here.

This concludes part 2 of the series. The third and final part of the blog will discuss unvalidated redirects and forwards, and common security misconfiguration.