DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Improving Java Code Security
  • How Dangerous Is Log4Shell and How it Affects the Java Industry?
  • How To Detect and Secure Your Java App From Log4j Vulnerabilities
  • Detecting Bugs and Vulnerabilities in Java With SonarQube

Trending

  • Getting Started With Agentic Workflows in Java and Quarkus
  • Multi-Scale Feature Learning in CNN and U-Net Architectures
  • S3 Vectors: How to Build a RAG Without a Vector Database
  • Build Self-Managing Data Pipelines With an LLM Agent
  1. DZone
  2. Coding
  3. Java
  4. Java Serialization Filtering — Prevent 0-Day Security Vulnerabilities

Java Serialization Filtering — Prevent 0-Day Security Vulnerabilities

A simple configuration that requires no code change can save you from a hack such as Log4Shell, even from vulnerabilities we don't know about yet!

By 
Shai Almog user avatar
Shai Almog
DZone Core CORE ·
Feb. 21, 23 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
3.1K Views

Join the DZone community and get the full member experience.

Join For Free

I’ve been a Java developer long enough to remember the excitement when Sun introduced the concept of serialization in the JVM. In the world of C, we could just write a struct into a file, but this was always problematic. It wasn’t portable and had many issues. But for Java, we could just write the class, and it “worked." This was pure magic!

Java was still mostly in use on the client side, and when we thought about security, we had different vulnerabilities in mind. The sandbox occupied most of our security discussions. Fast forward a couple of decades, and today when most developers discuss serialization, the discussion isn’t so positive. Serialization, as Brian Vermeer puts it, is: “the gift that keeps giving.”

In fact, just after I created this video, a new deserialization vulnerability in SnakeYaml was exposed. Serialization is one of the biggest security problems in many programming languages; it isn’t just a JVM problem. Hackers can use tools designed to deliver a serialization exploit chain. You can then generate a gadget used to deliver the exploit without too much knowledge of the system. That is scary stuff.

I’m not a security expert. I care more about the solution. How do we make sure that the next zero-day doesn’t affect us?

How do we harden our server code against serialization attacks? 

Do We Need Serialization?

We rarely need serialization. Ideally, if you can remove serialization entirely from your code and can avoid 3rd party code that uses serialization, you can block it completely. This will mean that even if a zero-day comes up, the serialization portion will fail. You might have a bug, but it won’t be an exploitable vulnerability.

Sometimes we need a bit of serialization. In that case, we can include only the well-known classes needed and block everything else out.

JEP 290: Serialization Filtering

The solution came in Java 9 in the form of serialization filtering as part of JEP 290. There are critical patch updates for older JDKs, such as JDK 8u121. So if you must stay in an older version, it’s still possible to use this feature.

It is possible to use this feature with no code changes, although we might want to change the code for additional functionality. The fundamental problem is testing that important systems don’t break. We might run into difficulty when verifying serialization usage, e.g., in distributed caching layers. A cache might serialize objects to synchronize them between nodes over the network. We might miss that dependency when running tests locally but fail in production. In those cases, you can follow the strategies listed below to solve the problems.

Whitelist vs. Blacklist

There are two approaches we can take when filtering specific serializable objects:

  • Whitelist — Block everything and allow specific classes or packages in.

  • Blacklist — Block specific problematic classes and packages.

A blacklist lets us block well-known vulnerabilities, and that might be enough. But we have no guarantee that we blocked everything. A whitelist is usually the more secure option, yet it might break your code if you missed a class that’s required in an edge case.

We can set the filter on the JDK itself by editing the java. security properties file. That might make sense if you package a JDK with your application. Personally, I prefer using the command line argument to configure that, e.g.:

 
java “-Djdk.serialFilter=!*” -jar MyJar.jar


This command will block all serialization. Notice I need to use the quotes to prevent bash from expanding the star sign. The exclamation point means we wish to block, and the star means we block everything.

The following code is a blacklist. We’re blocking a specific package. We can also narrow it down to a specific class. But as I said before, this isn’t ideal:

 
java “-Djdk.serialFilter=!mypackage.*” -jar MyJar.jar


Besides the inherent problems with the blacklist, a major problem is knowing what to block. There are obvious targets like classes that have been vulnerable in the past, e.g.:

  • java.rmi.server.UnicastRemoteObject

  • java.util.logging.Handler

  • java.util.zip.Inflater

  • org.apache.commons.collections.functors.InvokerTransformer

  • org.apache.commons.collections4.functors.InvokerTransformer

Unfortunately, this list is not exhaustive, and I couldn’t find any list that I can use as a source for a proper blacklist. We can look through the Common Vulnerabilities and Exposures (CVE) database for exploits, but that’s painstaking work.

Finally, we have a whitelist where we allow the classes under the package mypackage. We can serialize them as usual. The JVM seamlessly blocks everything else. This is pretty close to the ideal situation. We can add additional classes and packages as necessary by adding them and separating them with a semicolon:

 
java “-Djdk.serialFilter=mypackage.*;!*” -jar MyJar.jar


What About Complexity?

How do you know which classes are serialized in the code? How do you get an alert if your code blocked a serialization attempt? This might be something you would want to track since it might be the system breaking, or it might be an attempted hack. Both are valid reasons for an alert. You can’t do that declaratively, but you can write code that can use sophisticated logic to determine whether serialization should succeed.

This is a sample from the Oracle documentation of a simple serialization filter. Notice it can reject the serialization or leave it undecided. This is part of a filter chain where each stage in the validation process can reject the serialization or pass it on to the next stage. We can bind the filter globally as we do here or do it on a per-stream basis. The API is remarkably flexible and provides a lot of information about the process:

 
ObjectInputFilter.Config.setSerialFilter(info -> info.depth() > 10 ? Status.REJECTED : Status.UNDECIDED); 


TL;DR

You should always use serialization filtering when running a JVM deployment. This should always be the case. 

Serialization filtering was backported to older JVM versions, so there is absolutely no excuse.

Serialization filtering requires no code changes, and we can enable it via global configuration or command line.

At the very least, you can use it to blacklist known vulnerabilities. Ideally, we should block all serialization and whitelist specific classes or packages as needed.

Java virtual machine Serialization Vulnerability Blocks Java (programming language) security

Published at DZone with permission of Shai Almog. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Improving Java Code Security
  • How Dangerous Is Log4Shell and How it Affects the Java Industry?
  • How To Detect and Secure Your Java App From Log4j Vulnerabilities
  • Detecting Bugs and Vulnerabilities in Java With SonarQube

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook