Prevent xss vulerabilty by sanitizing user input with html cleaner plugin

What is XSS/Cros site scripting attack

From Wikipedia

Cross-site scripting (XSS) is a type of computer security vulnerability typically found in web applications. XSS enables attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. Cross-site scripting carried out on websites accounted for roughly 84% of all security vulnerabilities documented by Symantec as of 2007.

What is the solution 

The solution to prevent XSS attack is to never trust user input. User can enter malicious code/script any where in your application where you accept user inputs, such as text fields, text area etc. If you store the user input as it is without sanitizing it and render it on UI as part of html your application is vulenrable to XSS attack.

In this post I'll show how to use html-cleaner plugin to prevent xss attacks by sanitizing user entered text.

Html cleaner plugin is a whilelist based html sanitized built on top of jsoup library. Plugin makes it easy to define custom whitelists using a groovy DSL and adds helper methods to controller artifacts for sanitizing unsafe user entered text.

Step 1: Install plugin

Install the plugin by adding the following dependency in build.gradle file.

dependencies {
    compile 'org.grails.plugins:html-cleaner:3.0.0.1'
}

 Step 2: Define a white list

A white list a list of html tags that you wont to allow users to enter, all other tags will get removed. Jsoup comes with few predefined whitelists (basic, none, simpleText, basicWithImages, relaxed) See this link for more details. You can define additional custom whitelists in application.groovy using a DSL. Below is an example of a custom whitelist that allows just <b>, <p>, <span> and <a> tags. It also enforces rel=nofollow attribute on every user entered links.

htmlcleaner {
    whitelists = {
        whitelist("sample") {
            startwith "none"
            allow "b", "p", "span"
            allow("a") {
                attributes "href"
                enforce attribute:"rel", value:"nofollow"
            }  
        }
       
    }
}

A whitelist can extend another whitelist by specifying startsWith "whitelistname". Above whitelist starts with none, however you can create a whitelist which starts with one of the predefined jsoup whitelist or even a custom whitelist.

Step 3: Sanitize the user entered text 

Html cleaner plugin adds cleanHtml method to every controller which can be used to clean unsafe user entered text of any unwanted html tags or script.

class BookController{

  def save() {
    Book b = new Book()
    b.name = cleanHtml(params.name, "sample")
    b.description = cleanHtml(params.description, "sample")
    b.save()
    redirect action:"show", params:[id:book.id]
  }
}

The plugin registers a bean with name htmlCleaner which has a method cleanHtml with same signature as the method added to controllers. The htmlCleaner bean can be injected to service class If you need to sanitze the strings from services.


class BookService {
  def htmlCleaner

  Book save(String name, String description) {
    Book b = new Book()
    b.name = htmlCleaner.cleanHtml(name, "sample")
    b. description = htmlCleaner.cleanHtml(description, "sample")
    b.save()
    return b
  }
}

You can sanitize the text before storing to database. If you have unsafe text stored to database and you need to display it on UI, plugin provides a custom tag.

<hc:cleanHtml unsafe="${book.description}" whitelist="sample"/>