Event Listener module
Job module
Language module
Macro Module
Struts module
Theme module
Web UI modules
Workflow module

Rate this page:

Struts Complex Parameters and Security

This document describes changes that were made to the handling of Struts actions in Confluence between versions 2.9 and 2.10. All developers writing Struts plugins for Confluence 2.10 and later should take note of this.

Complex Struts Parameters

Struts allows the setting of complex parameters on a Struts action object. For example, a URL parameter of formData.name=Charles will be translated by Struts into the method calls getFormData().setName("Charles") by the Struts parameters interceptor. If getFormData() returns null, Struts will attempt to create a new object of the appropriate return type using its default constructor, and then set it with setFormData(newObject).

This leads to the potential for serious security vulnerabilities in Struts actions, as you can effectively call arbitrary methods on an Action object. This led to the Parameter Injection issues in Confluence Security Advisory 2008-10-14. In Confluence 2.9 this issue was worked around by filtering out all properties that were known to be dangerous, but for 2.10 a more complete solution that also protects against future vulnerabilities has been introduced.

Because this vulnerability (and its solution) can affect plugins, plugin authors must now take extra steps to support complex form parameters.

The @ParameterSafe Annotation

From Confluence 2.10 and onwards, complex parameters are not permitted unless they are accompanied by a Java-level annotation declaring that the parameter is "safe" for Struts to access. There are two ways to apply the annotation:

  • If a getter method is annotated with the @com.atlassian.xwork.ParameterSafe annotation, that method is accessible as a complex parameter
  • If a class is annotated with the @com.atlassian.xwork.ParameterSafe annotation, any complex parameter that is of that type is accessible

Only the initial method on the Struts action, or initial return value from the action class needs to be annotated, nested complex parameters do not need further annotation.

So in the example above, to make the formData parameter you would do one of the following:

1
2
@ParameterSafe
public FormData getFormData() { 
   return formData; 
}

or:

1
2
@ParameterSafe
public class FormData {
   ...
}

Be Careful

By placing the @ParameterSafe annotation on a method or class, you the developer are declaring that you have carefully inspected that code for potential vulnerabilities. Things to be careful of:

  • DO NOT return live Hibernate persistent objects, as users may change values on them directly with parameters, and then those changes will be saved to the database automatically
  • DO NOT return objects that contain setter methods that are used for anything but setting form parameter values, as those values will be reachable by URL parameter injection
  • DO NOT return objects that have Spring-managed beans, live components, or hibernate objects accessible through getter methods, as they will be accessible to URL parameter injection

Your safest bet is that if you are using an object to store complex parameters, make it a dumb: just setters that store state in the object itself and no further behaviour. Any more functionality than that is dangerous.

Rate this page: