Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Java Serialization Vulnerability Threatens Millions of Applications

DZone's Guide to

Java Serialization Vulnerability Threatens Millions of Applications

Contrast security is promoting their solution for a vulnerability that affects WebLogic, WebSphere, JBoss, Jenkins, and OpenNMS.

· Java Zone
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

A widespread vulnerability in Java environments leaves thousands of businesses seriously exposed. Despite lacking a clever name — ala Heartbleed, Shellshock, and POODLE — this vulnerability is poised to allow hackers to do damage across the Internet. And there’s no easy  way to protect applications en-masse. That means it will take organizations a long time to find and fix all the different variants of this vulnerability.

Contrast Security has a solution that uses our patented, powerful application security instrumentation platform to find and fix this problem both quickly and accurately. Contrast can identify this problem during development using our IAST (Interactive Application Security Testing) approach. And Contrast can also protect applications in production using our RASP (Runtime Application Self Protection) features to patch the problem immediately or generate security alerts, with no re-coding necessary. One Contrast agent installed on an application server can address the problem on all of the Java applications on that server.

To learn more about the details of the Java serialization flaw, keep reading. Serialization is a way that developers turn their data structures into a stream of bytes for transport or storage.  Deserialization is the reverse process that happens when the data is received. There have been security issues with serialization for a long time - going back to 2010 and before.  See http://www.ibm.com/developerworks/library/se-lookahead for the full history.  Just recently, exploits were published for a bunch of different Java environments -- which unfortunately appears to be the only way to make something happen in security. 

These flaws are serious and can be used to effect a complete remote command execution -- total host takeover on any application that accepts serialized objects. 

In Java, reading a BitSet from a serialized stream is as simple as:

     ObjectInputStream in = new ObjectInputStream( inputStream );

     return (Data)in.readObject();

The problem is that there’s no way to know what you’re deserializing before you’ve decoded it.  So an attacker can serialize a bunch of malicious objects and send them to your application.  Once you call readObject(), it’s too late.  In some ways it’s like an XXE problem, where an attacker can use a malicious DOCTYPE to generate attacks during XML parsing.  But in this case, there’s no easy way to turn off DOCTYPE processing. 

What's need is a way to allow deserialization, but make it impossible for attackers to create instances of arbitrary classes.  Something like this:

      List<Class<?>> safeClasses = Arrays.asList( BitSet.class, ArrayList.class );

      Data d2 = safeReadObject( Data.class, safeClasses, new FileInputStream( f ) );

This allows the developer to specify the return type and a list of the classes that they expect to show up in serialized objects.  When something unauthorized shows up, we should throw a SecurityException and block the attempt.  Turns out that it’s not too difficult to implement such a thing.  We just need to overload a bit of the ObjectInputStream implementation.  

Here’s a method that you can use to replace calls to readObject:

    @SuppressWarnings("unchecked")

    public static <T> T safeReadObject(Class<?> type, List<Class<?>> safeClasses, InputStream in ) throws IOException, ClassNotFoundException {

        return (T) new ObjectInputStream(in) {

            protected Class<?> resolveClass(ObjectStreamClass d) throws IOException, ClassNotFoundException {

                Class<?> clazz = super.resolveClass(d);

                if (clazz.isArray()

                    || clazz.isPrimitive()

                    || clazz.equals(type)

                    || clazz.equals(String.class)

                    || Number.class.isAssignableFrom(clazz)

                    || safeClasses.contains(clazz)) return clazz;

                throw new SecurityException("Attempt to deserialize unauthorized " + clazz);

            }

        }.readObject();

    }

This method overrides the resolveClass() method in ObjectInputStream and adds checks to make sure that any class loaded as part of the deserialization process is either not exploitable or contained in the whitelist of safe classes.  As an alternative, you could also blacklist the classes you don’t know — the ones known to be used in exploits — but this approach is doomed to failure.  There are simply too many so-called “gadgets” on the classpath of a modern application to effectively list all the possible exploits.

This simple check protects your applications without radical changes to your code. The first step is to search your code to find all the places that you’re vulnerable —and tomorrow, all Contrast users will receive an update that does just that. You’ll be notified all the places across your application portfolio where you’re exposed due to deserializing untrusted data!

Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat

Topics:
java ,security flaw

Published at DZone with permission of Jeff Williams, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}