In the previous post we examine particular Java Serialisation characteristics and design points that had a few unexpected consequences. In this post we’ll explore more around exploiting serialisation datastreams. How it’s possible to compromise systems silently and in different ways: from changing data, running arbitrary code or even crashing systems.
Constraints
Once the ability to compromise a serialised data stream has been achieved, the bad actors have multiple options. How constrained they are depends on a number of factors.
The primary limiting factor will be available code. Can the bad actor run arbitrary code or are they limited to only use what is installed in the target application? As an aside, it can often come as a shock to developers to learn that the Java Runtime supports loading code remotely via URL classloaders. A capability of the runtime from inception.
There is another inbuilt way to load code from a remote server which is much more relevant to serialisation. This mechanism is part of the javax.naming package. The particular class that can be the trigger for an attack is called javax.naming.Reference
This class, as its name implies, is a reference to another class external to the JVM. The class contains information about how to instantiate objects from the remote server. Including the actual URL where the code is stored. This means that if a serialised object stream contains a Reference object then arbitrary remote code can be trivially loaded and executed. The Log4Shell vulnerability is the exemplar of this technique. Note that later versions of the runtime and/or Log4J have settings that can reduce the exposure.
Other constraining factors are ensuring that any remote code is at a compatible version level with the local (Read more...)