H3rmesk1t
- 关注

C3P0 简介
c3p0is an easy-to-use library for making traditional JDBC drivers "enterprise-ready" by augmenting them with functionality defined by the jdbc3 spec and the optional extensions to jdbc2. As of version 0.9.5, c3p0 fully supports the jdbc4 spec.
In particular, c3p0 provides several useful services:
A class whichs adapt traditional DriverManager-based JDBC drivers to the newer javax.sql.DataSource scheme for acquiring database Connections.
Transparent pooling of Connection and PreparedStatements behind DataSources which can "wrap" around traditional drivers or arbitrary unpooled DataSources.
The library tries hard to get the details right:
c3p0 DataSources are both Referenceable and Serializable, and are thus suitable for binding to a wide-variety of JNDI-based naming services.
Statement and ResultSets are carefully cleaned up when pooled Connections and Statements are checked in, to prevent resource- exhaustion when clients use the lazy but common resource-management strategy of only cleaning up their Connections. (Don't be naughty.)
The library adopts the approach defined by the JDBC 2 and 3 specification (even where these conflict with the library author's preferences). DataSources are written in the JavaBean style, offering all the required and most of the optional properties (as well as some non-standard ones), and no-arg constructors. All JDBC-defined internal interfaces are implemented (ConnectionPoolDataSource, PooledConnection, ConnectionEvent-generating Connections, etc.) You can mix c3p0 classes with compliant third-party implementations (although not all c3p0 features will work with external implementations of ConnectionPoolDataSource).
环境搭建
<dependencies>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>8.5.27</version>
</dependency>
</dependencies>
URLCLassLoader
过程分析
com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase
本质上也是一个封装对象, 其中储存了PropertyChangeSupport
和VetoableChangeSupport
对象, 用于支持监听器的功能.
这个类在序列化和反序列化时, 要保存内部的ConnectionPoolDataSource
成员变量, 如果connectionPoolDataSource
本身是不可序列化的对象, 则使用ReferenceIndirector
对其进行引用的封装, 返回一个可以被序列化的IndirectlySerialized
实例对象.
跟进ReferenceIndirector#indirectForm
, 其中会调用ConnectionPoolDataSource
的getReference
方法返回一个Reference
对象, 并使用ReferenceSerialized
对象对其封装.
在反序列化时, 会调用其IndirectlySerialized#getObject
方法重新生成ConnectionPoolDataSource
对象.
ReferenceSerialized#getObject
调用InitialContext#lookup
方法尝试使用JNDI
来获取相应的对象, 在contextName
、env
均为空的情况下, 调用ReferenceableUtils#referenceToObject
使用Reference
中的信息来获取.
这里跟进ReferenceableUtils#referenceToObject
方法, 可以看到其使用了URLClassLoader
从URL
中加载了类并实例化, 于是可以通过插入恶意URL
来触发漏洞.
根据上文的分析, 构造一个不可序列化的并且实现了Referenceable
的ConnectionPoolDataSource
对象, 其getReference
方法返回带有恶意类位置的Reference
对象即可. 反序列化PoolBackedDataSourceBase
时会处理其中的ConnectionPoolDataSource
, 从而URLClassLoader
加载指定的恶意类.
BeanFactory
过程分析
在URLCLassLoader-Gadget
中利用的加载远程的恶意类, 当目标环境无法出网时, 则无法使用该方法. 在ReferenceableUtils#referenceToObject
中注意到, 当var0.getFactoryClassLocation()
值为null
时, 会默认加载而不是远程加载, 接着在调用getObjectInstance
方法, 这里可以参考JNDI
在高版本JDK
中的利用姿势, 参考Exploiting JNDI Injections in Java. 通过Tomcat
的getObjectInstance
方法调用ELProcessor
的eval
方法实现表达式注入, 当目标环境是Tomcat8
理论上是可以实现无网利用的.
JNDI
过程分析
有两个类对ConnectionPoolDataSource
进行了实现, 跟进其中的JndiRefConnectionPoolDataSource
, 其中会调用JndiRefDataSourceBase#setJndiName
方法(JndiRefForwardingDataSource
继承JndiRefDataSourceBase
中的setJndiName
方法)来获取jndiName
的值.
其次,JndiRefConnectionPoolDataSource
类中有LoginTimeout
属性及其setter
方法,
其setter
方法会调用内部WrapperConnectionPoolDataSource
对象的setLoginTimeout
方法, 追踪后会发现来到JndiRefForwardingDataSource#setLoginTimeout
.
跟进JndiRefForwardingDataSource#inner
, 其会调用JndiRefForwardingDataSource#dereference
, 再度跟进
此方法中会根据JndiRefForwardingDataSource#jndiName
属性进行lookup
问询, 而jndiName
属性从上文看是可以被JndiRefConnectionPoolDataSource#setter
方法控制的.
于是, 在Fastjson
、Jackson
等环境下, 调用JndiRefConnectionPoolDataSource
类的jndiname
、logintimeout
属性的setter
方法, 向jndiname
传入恶意RMI
服务器地址, 然后调用logintimeout#setter
方法使受害机去lookup
设置好的jndiname
中的恶意地址, 造成JNDI
注入.
Hex 序列化字节加载器
过程分析
在JNDI-Gadget
中是对ConnectionPoolDataSource
的实现类JndiRefConnectionPoolDataSource
进行的利用, 而这条Gadget
利用的则是WrapperConnectionPoolDataSource
.WrapperConnectionPoolDataSource
继承于WrapperConnectionPoolDataSourceBase
, 在WrapperConnectionPoolDataSourceBase
中存在属性userOverridesAsString
及其setter
方法setUserOverridesAsString
, 触发fireVetoableChange
事件处理.
在WrapperConnectionPoolDataSource
中存在方法setUpPropertyListeners
, 其中有一个判断语句, 当其属性为userOverridesAsString
时, 将调用parseUserOverridesAsString
方法.
跟进parseUserOverridesAsString
方法, 先对userOverridesAsString
进行截取操作, 然后完成十六进制解码, 然后调用fromByteArray
函数, 最终触发反序列化操作.
在Fastjson
、Jackson
环境, 此Gadget
更适合在不出网环境下利用.
参考
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
