ActiveMQ can send/receive JMS Object messages (ObjectMessage in ActiveMQ context) to comply with JMS specifications. Internally, ActiveMQ relies on
Java’s serialization mechanism for the marshaling and unmarshalling of the messages' payload.
Applications should restrict the types that can be unserialized from JMS messages.
Why is this an issue?
When the application does not implement controls over the JMS object types, its clients could be able to force the deserialization of arbitrary
objects. This may lead to deserialization injection attacks.
What is the potential impact?
Attackers will be able to force the deserialization of arbitrary objects. This process will trigger the execution of magic unmarshalling methods on
the object and its properties. With a specially crafted serialized object, the attackers can exploit those magic methods to achieve malicious
purposes.
While the exact impact depends on the types available in the execution context at the time of deserialization, such an attack can generally lead to
the execution of arbitrary code on the application server.
Application-specific attacks
By exploiting the behavior of some of the application-defined types and objects, the attacker could manage to affect the application’s business
logic. The exact consequences will depend on the application’s nature:
- Payment bypass in an e-commerce application.
- Privilege escalation.
- Unauthorized users' data access.
Publicly-known exploitation
In some cases, depending on the library the application uses and their versions, there may exist publicly known deserialization attack payloads
known as gadget chains. In general, they are designed to have severe consequences, such as:
- Arbitrary code execution
- Arbitrary file read or write
- Server-side request forgery
Those attacks are independent of the application’s own logic and from the types it specifies.
How to fix it in Java EE
Code examples
The following code example is vulnerable to a deserialization injection attack because it allows the deserialization of arbitrary types from JMS
messages.
Noncompliant code example
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
factory.setTrustAllPackages(true); // Noncompliant
Compliant solution
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
factory.setTrustedPackages(Arrays.asList("org.mypackage1", "org.mypackage2"));
How does this work?
The noncompliant code example calls the setTrustAllPackages
method that explicitly allows the deserialization of arbitrary types. On
the contrary, the compliant code example, thanks to the setTrustedPackages
method, defines a short list of classes allowed for the
deserialization.
While defining a short list of trusted types is generally the state-of-the-art solution to avoid deserialization injection attacks, it is important
to ensure that the allowed classes and packages can not be used to exploit the issue. In that case, a vulnerability would still be present.
Note that ActiveMQ, starting with version 5.12.2, forces developers to explicitly list packages that JMS messages can contain. This limits the risk
of successful exploitation. In versions before that one, calling the ActiveMQConnectionFactory
constructor without further configuration
would leave the application at risk.
Resources
Documentation
Standards