Friday, November 20, 2015

Clarification and Fix for Serialization Exploit

There have been reports of a Java serialization based epxloit (e.g. here), enabling the attacker to execute arbitrary code. As usual, there is a lot of half baked reasoning about this issue, so I'd like to present a fix for my fast-serialization library as well as tweaks to block deserialization of certain classes for stock JDK serialization.

In my view the issue is not located in Java serialization, but insecure programming in some common open source libraries.

Attributing this exploit to Java Serialization is wrong, the exploit requires door opening non-jdk code to be present on the server.

Unfortunately some libraries accidentally do this, however its very unlikely this is a wide spread (mis-) programming pattern.

How can a class at server side open the door ?

  • the class has to define readObject() 
  • the readObject() method has to be implemented in a way that allows to execute code sent from remote

I struggle to imagine a sane use case on why one would do something along the line of

"readObject(ObjectInputStream in) { Runtime.exec(in.readString()); }"


"readObject(ObjectInputStream in) { define_and_execute_class(in.readBytes()); }"

Anyway, it happened. Again: something like the code above must be present on the class path at server side, it cannot be injected from outside.

Fixing this for fast-serialization

  • fast-serialization 2.43 introduces a delegate interface, which enables blacklisting/whitelisting of classes, packages or whole package trees. By narrowing down classes being allowed for serialization, one can assure only expected objects are deserialized.

  • if you cannot upgrade to fst 2.43 for backward compatibility reasons, at least register a custom serializer for the problematic classes (see exploit details). As registered custom serializers are processed by fast-serialization before falling back to JDK serialization emulation, throwing an exception in the read or instantiate method of the custom serializer will effectively block the exploit.
  • There is no significant performance impact as this is executed on initialization only

Hotfixing stock JDK Serialization implementation

(Verfied for JDK 1.8 only)

Use a subclass of ObjectInputStream instead of the original implementation and put in a blacklisting/whitelisting by overriding this method in ObjectInputStream:

(maybe also check resolveProxyClass, I'm not sure wether this also can get exploited [probably not]).
This will have a performance impact, so its crucial to have a efficient implementation of blacklisting/whitelisting here.


  1. This will help close off some Java serialization attacks, but will not protect you from DoS attacks. See for details.

  2. "Whitelisting does not help"

    I disagree, code injection requires a door-opening class at server side. Proper whitelisting will shut down any attempt to make use of the exploit.

    Regarding the DOS sample (from your site): it does not show a vulnerability of serialization but of the implementation of AbstractSet.hashCode(). This could be DOS-attacked in various ways even if half-automated encodings like json are used.

    Ofc a 100% save use of serialization at protocol level would require a careful selection of what classes are allowed in the payload, however it is not inherently more insecure than other encodings, one just needs to be restrictive on the data being tranmitted.

    In general there is no 100% save software, so its always a trade-off in between development cost/technical limitation vs probability of being sucessfully attacked.

    Being save against a widely known, easy to perform exploit actually will reduce the probability of getting attacked by a factor of 10 or more.

    Same argument holds true for "security by obscurity": It actually lowers probabilty of getting attacked by random server scraping tools. It increases the cost for the attacker as he's required to work out a dedicated attack for your "obscure" software, which means the probability of being a victim is lowered significantly.

  3. > Being save against a widely known, easy to perform exploit actually will reduce the probability of getting attacked by a factor of 10 or more.

    I didn't say whitelisting didn't help. I said it wasn't enough. I did say obscurity didn't help.

    Whitelisting and encryption will reduce the probability of a successful attack by some unknown amount, and will cut down on automated attacks. But the problem is not automated attacks, it's attacks period. Once they have a compromised host and know that Java serialization is being used, then they are free to poke at it any way they feel like. Not only that, but they share information and keep up to date on flaws in Java. It doesn't matter if it's obscure to developers, only if it's obscure to the attackers.

    1. Good points, tend to agree. Obscurity does not lower vulnerability if the same "obscurity" is present in many places :). TL;DR if you are obscure be obscure in a unique way and this won't help if your site is specifically attacked.

    2. Yes -- site specific obscurity will help if the attacker is coming in from the outside, but will not help if the attacker is coming in from a compromised host, as they will be able to use that host's already configured channel to provide you with the malware.