Grails - Security

Security

Grails is no more or less secure than Java Servlets.

However Java servlets (and hence Grails) are extremely secure and largely immune to common buffer overrun and malformed URL exploits due to the nature of the Java Virtual Machine underpinning the code.

Web security problems typically occur due to developer naivety or mistakes, and there is a little Grails can do to avoid common mistakes and make writing secure applications easier to write.

Summary: What Grails automatically does

Grails has a few built in safety mechanisms by default.

  1. All standard database access via GORM domain objects is automatically SQL escaped to prevent SQL injection attacks
  2. The default scaffolding templates HTML escape all data fields when displayed
  3. Grails link creating tags (g:link, g:form, g:createLink g:createLinkTo and others) all use appropriate escaping mechanisms to prevent code injection
  4. Grails provides codecs to allow you to trivially escape data when rendered as HTML, JavaScript and URLs to prevent injection attacks here.

Providing login and page level security

Currently Grails does not supply any implementation for this. There are multiple security plugins, including Spring Security, Shiro, and Authentication, and if your needs are very simple you can guard your application with Grails filters.

Securing your application from attack

What are the most common web security problems?

SQL injection

Hibernate, which is the technology underlying GORM domain classes, automatically escapes data when committing to database so this is not an issue. However it is still possible to write bad dynamic HQL code that uses unchecked request parameters.

Phishing

This really a public relations issue in terms of avoiding hijacking of your branding and a declared communication policy with your customers. Customers need to know how to identify bonafide emails received.

XSS - cross-site scripting injection

It is important that your application verifies as much as possible that incoming requests were originated from your application and not from another site. Ticketing and page flow systems can help this.

It is also important to ensure that all data values rendered into views are escaped correctly. For example when rendering to HTML or XHTML you must call encodeAsHTML() on every object to ensure that people cannot maliciously inject JavaScript or other HTML into data or tags viewed by others. Grails supplies several Dynamic Encoding Methods for this purpose and if your output escaping format is not supported you can easily write your own codec.

You must also avoid the use of request parameters or data fields for determining the next URL to redirect the user to. If you use a successURL parameter for example to determine where to redirect a user to after a successful login, attackers can imitate your login procedure using your own site, and then redirect the user back to their own site once logged in, potentially allowing JS code to then exploit the logged-in account on the site.

HTML/URL injection

This is where bad data is supplied such that when it is later used to create a link in a page, clicking it will not cause the expected behaviour, and may redirect to another site or alter request parameters.

HTML/URL injection is easily handled with the codecs introduced in Grails 0.4, and the taglibs supplied with grails use encodeAsURL where appropriate. If you create your own tags that generate URLs you will need to be mindful of doing this too.

Denial of service

Load balancers and other appliances are more likely to be useful here, but there are also issues relating to excessive queries for example where a link is created by an attacker to set max=1000000 so that a query could exceed the memory limits of the server or slow the system down. The solution here is to always sanitize request parameters before passing them to dynamic finders or other GORM query methods:

def safeMax = Math.min(params.max?.toInteger(), 100) // never let more than 100 results be returned
return SomeClass.list(max:safeMax)

Guessable IDs

Many applications use the last part of the URL as an "id" of some object to retrieve from GORM or elsewhere. Especially in the case of GORM these are easily guessable as they are typically sequential integers.

Therefore you must assert that the requesting user is allowed to view the object with the requested id before returning the response to the user.

Not doing this is "security through obscurity" which is inevitably breached, just like having a default password of "letmein" and so on.

You must assume that every unprotected URL is publicly accessible one way or another.