Intelligence Driven Security

Pwning Your Java Messaging With Deserialization Vulnerabilities
Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 1

1 Introduction to Java’s Serialization problem

1.1 Overview
Java deserialization vulnerabilities are a bug class on its own. Although several security researchers have published details in the past,the bug class is still fairly unknown.
In 2015 Christopher Frohoff and Gabriel Lawrence of Qualcomm published great research with their presentation ”Marshalling Pickles” at AppSecCali 20151 . They presented several unique exploitation vectors for common
third party libraries and also the tool ysoserial, used to generate payloads for easy exploitation of deserialization
vulnerabilities.
Since then, several researchers have been further researching Java deserialization and numerous vulnerabilities
were found in commercial and open-source products.

1.2 The core problem
Suppose the following lines of Java Code are found in an application. The ObjectInputStream instance reads anobject from untrusted input using the readObject()-method.
...
ObjectInputStream untrustedInput = new ObjectInputStream(...);
Object inObject = (Object) untrustedInput.readObject();...

Listing 1.1: Deserializing an object from untrusted input
During the process of deserialization several methods are invoked on objects of classes implementing the java
.io.Serializable-interface. Speciﬁcally, the methods readResolve() and readObject() are invoked by the1 http://www.slideshare.net/frohoff1/appseccali-2015-marshalling-pickles

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 2

ObjectInputStream class on serializable objects, thus allowing to trigger code to be executed. If the code isreading from the untrusted input stream and invoking potentially unsafe methods (e.g. reflection), this can be
exploited.

1.3 Code reuse attacks with gadgets
For exploiting deserialization vulnerabilities we need to ﬁnd serializable classes with methods doing ﬁle writes,
dynamic methods calls, JNDI lookups, etc. and reuse them. If those methods can be triggered during deserialization of an object (e.g. readObject), we can reuse them as a gadget for exploitation. Several gadgets were
found by security researchers in Java third party libraries (e.g. Commons Collection) or even the Java Runtime
Environment.

1.4 Ysoserial - Making exploitation easy
Ysoserial is a ”Proof of Concept”-tool to support the exploitation of Java deserialization vulnerabilities. It was
released by Chris Frohoff and Gabriel Lawrence at AppSecCali 2015. Furthermore, researchers have been contributing new gadgets so that ysoserial is admitted as the public repository for deserialization gadgets.

Figure 1.1: Generating a serialized object stream with Ysoserial

At the time of writing, ysoserial allows to generate serialized gadgets for around 12 different libraries.

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 32 The Java Message Service
The Java Message Service (JMS) is an API for sending messages asynchronously using Message-OrientedMiddleware (MOM). Several versions of the standard exists:• JMS 1.0.2b (no JSR, 2001)• JMS 1.1 (JSR 914, released 2002)• JMS 2.0 (JSR 343, released 2013)• JMS 2.1 (JSR 368, currently in Early Draft Review phase)
JMS is also an integral part of Java EE since version 1.4, thus requiring all Java EE application servers to support
it. The latest version 2.0 of JMS is part of JEE7. With OpenMQ Oracle maintains a reference implementation for
JMS 1.1/2.0 .

2.1 Products supporting JMS
Several Java enterprise products support JMS, either as JMS Broker or JMS client.

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 4

Figure 2.1: Products supporting JMS

JMS Brokers provide clients with connectivity and message storage and delivery functions. JMS brokers usually
run as a standalone application or as an embedded broker inside a JEE application server. Integration Platforms
such as Enterprise Service Buses mostly have embedded brokers but also can act as a JMS Client only.

2.2 Wire Protocols
Since JMS is only an Application Programming Interface(API), it doesn’t require any speciﬁc wire protocol to
be implemented. In the past JMS providers implemented JMS on top of proprietary protocols. Since several
years open standards exit and were adopted by vendors. The most important ones found in open-source andcommercial products are:
• AMQP - Advanced Message Queuing Protocol• MQTT - MQ Telemetry Transport• STOMP - Streaming Text Oriented Messaging Protocol• OpenWire• Websocket
Just as a side note, JMS Brokers also often provide separate Java APIs for speciﬁc protocols like AMQP, MQTT
and STOMP. But those APIs do not follow any standard. This is also one of the reason whys JMS is still used inmodern systems.
The following Figure 2.2 shows the supported wire protocols of various message brokers along with default
ports for each supported protocol.

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 5Figure 2.2: JMS broker supported wire protocols with default broker ports (without SSL)

Wire protocol/port combinations marked as red are of special interest as those are supported in the JMSimplementation of the broker and hence are in the focus for our research.

2.3 JMS Basics
JMS deﬁnes several key entities as shown in Figure 2.3.

Figure 2.3: JMS key entities

JMS Broker
JMS Client
Message

Provide clients with connectivity and message storage and delivery functions
An application that uses the services of the message broker
A Message object comprised of header, properties and payload

Destination
Connection

The destination to where a message is sent
Permanent interaction of a JMS client with a broker using a speciﬁc protocol and credentials

Session

Used for a transactional context if required

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 6

JMS provides two different communication models implemented in different destination types:

JMS Queue
A queue allows a producer to send a message to a destination and exactly one consumer will receive it from thedestination .

Figure 2.4: ”Point-To-Point” communication model

JMS Topic
To support multiple receivers, JMS provides topic destinations. A publisher sends a message to a topic and themessage gets distributed to all subscribers by the broker.

Figure 2.5: ”Publish/Subscribe” communication model

Depending on the broker implementation destinations need to be deﬁned beforehand or can be created at runtime. JMS also supports the creation of temporary destinations using methods of the JMS API.

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 7

2.4 The JMS API
The JMS API implements the key concepts as described in section 2.3. Figure 2.6 shows a good overview how
the key entities interact (for details see 1 ).

Figure 2.6: Overview of the JMS API

Listing 2.1) shows a JMS client sending a message to the queue ”orders”. Receiving a message using a MessageConsumer is shown in Listing 2.2. Both sending and receiving require ﬁrst to set up a Connection using theConnectionFactory and then to establish a Session. A ConnectionFactory instance can be referenced/createdeither by using the Java Naming and Directory Service (JNDI) or programmatically by using the JMS implementation classes. In both examples the ConnectionFactory implementation of Apache ActiveMQ is used. ConnectionFactory objects encapsulate JMS implementation dependent conﬁgurations like the protocol, target address
and port to be used. The Enterprise Java Bean (EJB) technology, as included in all JEE standard versions, deﬁnes three different serverside component models called ”Enterprise Java Beans”. To support JMS in serversideenvironments, the ”Message Driven Bean” component has been introduced in EJB 2.0 (2001). Message Driven
Beans require to implement the javax.jms.MessageListener-interface which deﬁnes the method onMessage(). The
onMessage()-method is called by the embedded JMS broker of an JEE application server, when a message has
been received.
1 ”The Java EE 6 Tutorial - The JMS API Programming Model”

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Producer {public static void main(String[] args) throws Exception{
ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://broker:61616");
Connection connection = factory.createConnection("user", "pass");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("orders");
MessageProducer producer = session.createProducer(queue);connection.start();TextMessage message = session.createTextMessage();message.setText("This is the payload");producer.send(message);connection.close();}}Listing 2.1: Sending a TextMessage using the JMS API

Page 8

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 9import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Consumer {public static void main(String[] args) throws Exception {ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://broker:61616");
Connection connection = factory.createConnection("user", "pass");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("orders");
MessageConsumer consumer = session.createConsumer(queue);connection.start();Message message = consumer.receive();if (message instanceof TextMessage) {System.out.println(((TextMessage) message).getText());}
connection.close();}}Listing 2.2: Receiving a TextMessage using the JMS API

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destination", propertyValue = "cwqueue"),@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") },mappedName = "cwqueue")public class CwMessageDriven implements MessageListener {public void onMessage(Message message) {try {if (message instanceof TextMessage) {System.out.println(((TextMessage) message).getText());}} catch (Exception e) {}}}Listing 2.3: Receiving a TextMessage using a Message-Driven Bean

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 10

2.5 JMS messages
The JMS standard requires a JMS provider to implement ﬁve different message types. As shown in Figure 2.7
message types are deﬁned as interfaces.

Figure 2.7: JMS message type hierarchy

Every JMS message consists of a header, properties and a body (see Figure 2.8). The JMS header contains
predeﬁned header ﬁelds such as ”JMSMessageID” or ”JMSTimestamp” (see 2 for more details).
The message properties contain a set of key/value pairs which can be set by a JMS client. Furthermore themessage properties allow to implement selectors to ﬁlter JMS messages. For details on message selectors see
3.

Figure 2.8: Message structure
2 The Java EE 6 Tutorial

3 The Java EE 6 Tutorial - JMS Message Listeners

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 11

The following message type deﬁnitions are taken from the JMS 1.1 speciﬁcation:

Figure 2.9: Message types from the JMS 1.1 speciﬁcation

The ObjectMessage type is of special interest as it requires a JMS provider to implement (de)-serialization basedon the Java Object Serialization Speciﬁcation (see 4 ). An ObjectMessage provides two methods. With the setObject()-method a serializable object is stored into the ObjectMessage. And with the getObject()-method the object
is reconstructed from the message body.
package javax.jms;
import java.io.Serializable;
public abstract interface ObjectMessage
extends Message{
public abstract void setObject(Serializable paramSerializable)
throws JMSException;
public abstract Serializable getObject()
throws JMSException;}

Listing 2.4: Interface deﬁnition of ObjectMessage

4 https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 123 Attacking JMS

3.1 Vulnerability Discovery and Patch Status
Code White’s research focused on JMS client libraries of JMS brokers and Java EE application servers. We
haven’t looked at integration platforms at all because they are often based on JEE application servers (e.g. Oracle
Weblogic and IBM WebSphere).
Several Java EE application servers implement JMS capabilities by embedding a JMS broker:
Java EE server

Embedded JMS Broker

IBM WebSphere

IBM WebSphere MQ

Oracle GlassFish
Redhat EAP <7 (WildFly <10)
Redhat EAP >=7 (WildFly >=10)

Oracle OpenMQ
Redhat HornetQ
Apache ActiveMQ-Artemis

Table 3.1: Java EE application servers with embedded JMS brokers

As already mentioned in section 2.5 the ”ObjectMessage” message type conveys a serialized object. All ObjectMessage implementations were found vulnerable to deserialization of untrusted input. Table 3.2 shows thevulnerabilities found in JMS client libraries and the corresponding patch status.

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 13#

VendorTargetVendor Discl.

CVE

Patch

1

ApacheActiveMQ

09/02/2015

CVE-2015-5254

Yes

2
3

Redhat/Apache
OracleHornetQ
OpenMQ

03/18/2016
03/18/2016

No
No

No
No

4
5
6

IBM
OraclePivotal

WebSphereMQ
Weblogic
RabbitMQ

03/18/2016
03/18/2016
03/24/2016

No
CVE-2016-0638
No

No
Yesa
No

7
8

IBM
IIT Software

MessageSight
SwiftMQ

03/24/2016
05/30/2016

CVE-2016-0375
No

Yes
No

9
10
11

ApacheApacheApacheActiveMQ Artemis
QPID JMS Client
QPID Client

06/02/2016
06/02/2016
06/02/2016

No
CVE-2016-4974
CVE-2016-4974

No
Yes
Yes

12

AmazonSQS Java Messaging

06/14/2016

No

No

Table 3.2: Affected JMS client libraries with patch statusa Oracle implemented blacklisting of gadget classes

3.2 Vulnerability Exploitation
Exploitation of deserialization vulnerabilities in ObjectMessage implementations is straight-forward. It just requires to send a serialized gadget in an ObjectMessage to the target destination of a JMS broker.
ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://broker:61616");
Connection connection = factory.createConnection("user", "pass");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("target");MessageProducer producer = session.createProducer(queue);connection.start();ObjectMessage message = session.createObjectMessage();message.setObject(-->PUTYOURGADGETHERE <--);
producer.send(message);connection.close();Listing 3.1: Exploitation of ObjectMessage-implementations

As soon as the message consumer receives the ObjectMessage and invokes the getObject() method on it, thepayload gets deserialized. Since the message consumer might expect a different object, chances are high thata ClassCastException will occur. Message brokers usually try to redeliver the message several times and give up
in the end.

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 14

3.3 Exploitation Success Factors
Successful exploitation depends on several factors:• Which JRE version is used (relevant for JDK gadgets)?
• Which libraries are bundled with the application?
• Which libraries are in the classpath of the Runtime Environment (e.g. Application Server)?
• Has the Runtime Environment separate classloaders with limited resolution scope (e.g. OSGI)?
• Is the Java Security Manager enabled ?
Since JMS is asynchronous there is neither feedback nor an error message/stack trace. As a result, Code Whitedeveloped a tool for blackbox assessment of JMS.

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 15

4 The Java Message Exploitation Tool
The Java Message Exploitation Tool (JMET) is a simple command line tool to make exploitation of ObjectMessage implementations easy. It integrates Chris Frohoffs’/Gabriel Lawrence’s ”Ysoserial”-tool for gadget payload
generation. The focus of JMET lies in the exploitation of deserialization flaws but it also supports the exploitationof XML parsers using XXE. Furthermore, custom scripts written in Javascript can be used to integrate further
common serialization technologies like XStream, Jackson, Kryo, etc.

4.1 Supported JMS client libraries
Currently, JMET supports the following client libraries of JMS brokers.
#

VendorTargetSupported

1
2

ApacheRedhat/Apache

ActiveMQ
HornetQ

Yes
Yes

3
4
5

OracleIBM
Oracle

OpenMQ
WebSphereMQ
Weblogic

Yes
Yes
No

6
7

PivotalIBM

RabbitMQ
MessageSight

Yes
No

8
9
10

IIT Software
ApacheApacheSwiftMQ
ActiveMQ Artemis
QPID JMS Client

Yes
Yes
Yes

11
12

ApacheAmazonQPID ClientSQS Java Messaging

Yes
No

Table 4.1: By JMET supported JMS client libraries

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 16

4.2 Basic usage
Using JMET is straight-forward. Three exploitation modes are implemented: ”ysoserial”, ”XXE” and ”Custom”(see 1 ). The target JMS implementation can be selected with ”impl”. With ”-Q” (”Queue”) or ”-T” (”Topic”) you
can select the target destination. If required you can specify a username (”-u”) and a password (”-pw”). JMS
implementation dependent options can also be conﬁgured using ”-Z” switches.

Figure 4.1: Command line parameters of JMET

4.3 Gadget exploitation
The deserialization gadget mode is the most interesting one as it allows to achieve reliable remote code execution. The command to be executed is speciﬁed after the ”ysoserial” switch. With the switch ”payload” you canalso select a payload to be used.
1 Details about the modes ”XXE” and ”Custom” can be found on JMET’s github project page”

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 17

Figure 4.2: Sending gadgets to queue ”event” using JMET

Since JMS is asynchronous, it might happen that more than one gadgets might be executed on the target system. In order to ﬁnd out which gadget works, you can use an Out-Of-Band channel like DNS and the substitution
mode. This mode substitutes the string ”§§” with the payload name to be executed (see Figure 4.3).

Figure 4.3: Using substitution to pass the payload name to the command to be executed

4.4 Tamper scripts
Tamper scripts allow to tamper the message before sending. Scripting was implemented using Java’s native
scripting support (JSR 223: Scripting for the Java Platform). Currently only ECMAScript is supported in JMET.
A good introduction can be found here (see 2 ).
The following script modiﬁes the javax.jms.Message instance by setting the JMSPriority.
function filter(message){message.setJMSPriority(3);print("Changed Priority")
return message;}

Listing 4.1: Setting the JMSPriority header value using a tamper script
2 https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/intro.html

Pwning Your Java Messaging With Deserialization Vulnerabilities – Matthias Kaiser of Code WhiteBlackhat USA 201608/03/2016

Page 18

5 Conclusion
All JMS client libraries analysed by Code White were found vulnerable to deserialization of untrusted input if
message of type ObjectMessage are used. Although Java messaging is used in enterprise systems heavily, no
general attack vector has been shown to get reliable code execution.
Because of the asynchronous communication of JMS, no feedback is given during exploitation using gadgets.
With JMET, blackbox assessments of JMS destinations are now made easy.