alex qiu
alex qiu

Reputation: 11

How to prevent XSS in play framework 2?

according to https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#XSS_Prevention_Rules_Summary

in play framework 2 document, I only can find method @Html to escape html. how to deal with other condition?

Upvotes: 0

Views: 3275

Answers (3)

asksharmadeepak
asksharmadeepak

Reputation: 49

As per Play Framework 1.2.4 docs: You can use flag

future.escapeInTemplates=true , In application.conf setting which will help you to block cross site scripting attack.

From docs :

It is strongly recommended to enable this option. When you really need to insert unescaped HTML in your templates, you can do so using the raw() method on the string. But if the string comes from a user input, you need to make sure it is sanitized first. When sanitizing user inputs, always prefer whitelisting (only allow a list of safe tags) to blacklisting (forbid a list of unsafe tags and allow all the rest).

Upvotes: 0

r.piesnikowski
r.piesnikowski

Reputation: 2961

I've created a simple trait XssFilter in my web application and I use it in my backend like this:

import java.util.regex.Pattern;
trait XssFilter {
  def filter(input: String): String = {
    var value: String = input;
    if (value != null) {
      // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
      // avoid encoded attacks.
      // value = ESAPI.encoder().canonicalize(value);

      // Avoid null characters
      value = value.replaceAll("", "");

      // Avoid anything between script tags
      var scriptPattern: Pattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE)
      value = scriptPattern.matcher(value).replaceAll("");

      // Avoid anything in a src='...' type of expression
      scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      value = scriptPattern.matcher(value).replaceAll("");

      scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      value = scriptPattern.matcher(value).replaceAll("");

      // Remove any lonesome </script> tag
      scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
      value = scriptPattern.matcher(value).replaceAll("");

      // Remove any lonesome <script ...> tag
      scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      value = scriptPattern.matcher(value).replaceAll("");

      // Avoid eval(...) expressions
      scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      value = scriptPattern.matcher(value).replaceAll("");

      // Avoid expression(...) expressions
      scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      value = scriptPattern.matcher(value).replaceAll("");

      // Avoid javascript:... expressions
      scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
      value = scriptPattern.matcher(value).replaceAll("");

      // Avoid vbscript:... expressions
      scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
      value = scriptPattern.matcher(value).replaceAll("");

      // Avoid onload= expressions
      scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      value = scriptPattern.matcher(value).replaceAll("");
    }
    return value;
  }
}

And use like this:

case class FormHelper(requestBody: AnyContent) extends XssFilter {
  def getAsFormUrlEncoded(key: String): String = {
    var ret = ""
    requestBody.asFormUrlEncoded.get.get(key) match {
      case None => {
        requestBody.asFormUrlEncoded.get.get(key + "[]") match {
          case None => ret = ""
          case s: Some[Seq[String]] => {
            ret = s.get.mkString(",")
          }
        }
      }
      case s: Some[Seq[String]] => ret = s.get.head
    }
    filter(ret)
    //requestBody.asFormUrlEncoded.get(key)(0)
  }
}

And finally somewhere in your controller code:

val fh = FormHelper(request.body)
val transId: String = fh.getAsFormUrlEncoded("transId")

Upvotes: 3

kravietz
kravietz

Reputation: 11285

In general Play Framework provides pretty good protection against XSS by default when using built-in templates (see Escaping section in docs). The @Html method does the opposite, disabling the escaping for the purpose of rendering raw, trusted HTML.

Upvotes: 3

Related Questions