RSS Feed
更好更安全的互联网

Liferay Portal Json Web Service Deserialization Vulnerability (CVE-2020-7961) Analysis

2020-11-02

Author:Longofo@Knownsec 404 Team 
Time: March 27, 2020 
Chinese version:https://paper.seebug.org/1162/

A vulnerability on Liferay Portal JSON Web Service RCE was previously posted on CODE WHITE. At first, my friends were dealing with this vulnerability, and I went to see it later. Liferay Portal uses Flexjson library for JSON Web Service processing in 6.1 and 6.2 versions, and replaced it with Jodd Json after version 7.

In summary, the vulnerability is: Liferay Portal provides Json Web Service service. For some endpoints that can be called, if a method provides Object parameter type, then we can construct an exploitable malicious class that conforms to Java Beans and pass the constructed json deserialization string, Liferay will automatically call the setter method of the malicious class and the default constructor when deserializing. However, there are still some details, and I feels quite interesting. In this article, the analysis of Liferay using JODD deserialization.

JODD Serialization And Deserialization

Refer to the Official User Manual, first look at the direct serialization and deserialization of JODD:

TestObject.java:

TestObject1.java

Test.java

Output:

In Test.java, two ways are used. First one is the commonly used way. The root type is specified when deserializing. The second official does not recommend this,security issues are exist. Assume up this application provides a place to receive JODD Json, and uses the second way, you can deserialize any type specified。The Liferay vulnerability is not caused by this reason, because it does not use setClassMetadataName("class").

Liferay's Packaging For JODD

Liferay does not directly use JODD for processing, but repackages some functions of JODD. The code is not long, so we will use JODD separately to analyze Liferay's packaging of JsonSerializer and JsonParser.

JSONSerializerImpl

Liferay's wrapper for JODD JsonSerializer is the com.liferay.portal.json.JSONSerializerImplclass:

It can be seen that some functions of the JODD JsonSerializer are set during serialization.

JSONDeserializerImpl

Liferay's wrapper for JODD JsonParser is the com.liferay.portal.json.JSONDeserializerImpl class:

It can be seen that some functions of the JODD JsonParser are also set when deserializing.

Liferay Vulnerability Analysis

Liferay provides hundreds of webservices that can be called in the /api/jsonws API. The servlet responsible for processing the API is also directly configured in web.xml:

look at this methods:

Seeing this, something occur.We can pass parameters for method calls. There are p_auth for verification, but deserialization is before verification, so that value does not works for exploit. According to the analysis of CODE WHITE, there are method parameters with parameter type Object, so guess that we can pass in any type of class. We can first debug the normal packet capture call to debug, and here does not write the normal call debugging process, simply look at the post parameters:

In general, Liferay first finds the method corresponding to /announcementsdelivery/update-delivery-> other post parameters are method parameters-> when each parameter object type is consistent with the target method parameter type-> Restore the parameter object-> call this method with reflection. However, there is no type specification for packet capture, because most types are String, long, int, List, map and others,JODD will automatically handle it when deserializing. In this section,how to specify a specific type?

The author mentioned in the article that Liferay Portal 7 can only specified rootType for invocation. This is also the case from the above Liferay's JODD JSONDeserializerImpl packaging. If you want to restore a specific object when a method parameter is of type Object,maybe it will parse the data, obtain the specified type, and then call the parse (path, class) method of JODD using specific type to restore it ;maybe Liferay not do. However, it can be seen from the author's analysis that Liferay did. The author looked up the call graph of jodd.json.Parser#rootType (envy such a tool):

looking up this, the author found a place where a root type could be specified. In com.liferay.portal.jsonwebservice.JSONWebServiceActionImpl#JSONWebServiceActionImpl call the com.liferay.portal.kernel.JSONFactoryUtil#looseDeserialize(valueString, parameterType ), looseDeserialize calls JSONSerializerImpl, and JSONSerializerImpl calls JODD's JsonParse.parse.

And the call on com.liferay.portal.jsonwebservice.JSONWebServiceActionImpl#JSONWebServiceActionImpl is the process of Liferay parsing the Web Service parameters. Its upper levelJSONWebServiceActionImpl#_prepareParameters(Class <?>), The JSONWebServiceActionImpl class has a _jsonWebServiceActionParameters attribute:

This property also holds a JSONWebServiceActionParametersMap. In its method, when the parameter starts with+, its put method splits the passed parameters with:, before : is parameter name,after : is type name:

The put parsing operation is completed in com.liferay.portal.jsonwebservice.action.JSONWebServiceInvokerAction # _executeStatement:

Through the above analysis and author's article, we can know the following points:

  • Liferay allows us to call web service methods via /api/jsonws/xxx
  • The parameter can start with +, use : to specify the parameter type
  • JODD JsonParse will call the class's default constructor and the setter method corresponding to the field

So we need to find the class that has malicious operations in the setter method or the default constructor. Look at the exploitation chain that marshalsec has provided,we can directly find the inherited exploitation chain. Most of them are also suitable for this vulnerability,it also depends on whether it exists in Liferay. Here are the test com.mchange.v2.c3p0.JndiRefForwardingDataSource, use the service/expandocolumn/add-column, because it has java.lang.Object parameter:

Payload is as follows:

Parsed the parameter type, deserialized the parameter object, and finally reached the jndi query:

Patch Analysis

Liferay patch adds type checking, in com.liferay.portal.jsonwebservice.JSONWebServiceActionImpl # _checkTypeIsAssignable:

_JSONWS_WEB_SERVICE_PARAMETER_TYPE_WHITELIST_CLASS_NAMES contains all whitelist classes in portal.properties. Basically, all whitelist classes start with com.liferay.


Paper

本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1163/

作者:江 | Categories:技术分享 | Tags:

发表评论