XWork Plugin Complex Parameters and Security

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

Complex XWork Parameters

XWork allows the setting of complex parameters on an XWork action object. For example, a URL parameter of formData.name=Charles will be translated by XWork into the method calls getFormData().setName("Charles") by the XWork parameters interceptor. If getFormData() returns null, XWork 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 XWork 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 XWork 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 accessable 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 XWork 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:

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

or:

@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.

Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport