This vulnerability is a design flaw in how Adobe LiveCycle, Adobe BlazeDS and GraniteDS handle the AMF protocol, that can be exploited resulting in arbitrary code execution.
The basis of how the deserialization of AMF data works, is that the data contains a class name, names of properties, and values for those properties. The application then creates an instance of that class by calling its constructor (without arguments), and using the Java beans conventions for getters and setters to set the properties in that newly created object.
That basic idea is already the security vulnerability. It does not put any limitation on which classes a client can cause to be instantiated (besides that they need a constructor without arguments), and which getters and setters on it may be called. It can be classes that have nothing to do with BlazeDS/GraniteDS or the services being exposed, but just happen to be available on the same server. For most classes this is safe. Constructors, getters, and setters usually don’t have extra side-effects outside of the objects they’re being called on. But there is no rule anywhere saying that that must always be the case; and in many applications there are classes available where calling the right setters leads to running arbitrary code.
Affected
- Adobe LiveCycle Data Services 3.1, 2.6.1, 2.5.1 and earlier versions
- Adobe LiveCycle 9.0.0.2, 8.2.1.3, 8.0.1.3 and earlier versions
- Adobe BlazeDS 4.0.1 and earlier versions
- GraniteDS Data Services 2.2.0 and earlier versions
Solution
- Security updatefor LiveCycle Data Services, LiveCycle ES, and BlazeDS
- Granite Data Services 2.2.1 GA
Note that for BlazeDS upgrading to the new version is not enough. You also need to configure the DeserializationValidator (as explained in blz401_hf_21287.txt included in the hotfix), otherwise you are still vulnerable.
For BlazeDS 3.x, Adobe will not release a fix, but the changes have been backported, so you can grab BlazeDS 3 nightly build 3.3.0.20931.
Theoretical example exploit
Suppose in some application or library, there is a class with the following code:
public class Foo {
public void setBar(String bar) throws IOException {
Runtime.getRuntime().exec(bar);
}
}
That class itself is not a security problem. In any Java application not using BlazeDS, this is perfectly safe code. But if it is available in the classpath of BlazeDS, it can be abused to execute any command, by sending (the binary AMF representation of) an object of this class with a “bar” attribute.
That’s a forced example. In the real world, such obvious exploits usually aren’t available. It just takes a bit more effort…
JFrame exploit
This exploit does not result in arbitrary code execution, but it’s a cute little example, in the Java library itself, just to show you a real-world case.
JFrame is the base class for windows shown on the screen in Swing. Sending an object with class “javax.swing.JFrame” and setting “visible” to “true” shows an actual window on the server running BlazeDS. As a bonus, the “defaultCloseOperation” could be set to 3 (EXIT_ON_CLOSE) so that if the window would be closed, the BlazeDS server exits. Some other stuff could be put in this window, but what can be shown and the behaviour the attacker can choose is quite limited (because of only being able to use getters and setters).
Sample Flex exploit code:
[RemoteClass(alias="javax.swing.JFrame")]
public class JFrame {
public var title:String = "Gotcha!";
public var defaultCloseOperation:int = 3;
public var visible:Boolean = true;
}
Arbitrary code execution
There exists an exploit that will work in many BlazeDS/GraniteDS applications, that leads to arbitrary code execution. But I’m not making that one public yet.
[Edit 17/6: added note about the fix for BlazeDS]