MYSQL JDBC XXE漏洞分析
字数 1105 2025-08-03 16:47:09
MySQL JDBC XXE漏洞分析与防御指南
漏洞概述
MySQL JDBC驱动在8.0.27版本之前存在XXE(XML External Entity)漏洞,攻击者可通过构造恶意XML数据引入外部实体,导致XXE攻击。
影响版本:MySQL JDBC < 8.0.27
漏洞原理分析
漏洞位置
漏洞主要存在于MysqlSQLXML#getSource方法中,当处理DOMSource类型时,未对传入的XML数据进行安全校验。
关键代码分析
public <T extends Source> T getSource(Class<T> clazz) throws SQLException {
// ...
else if (clazz.equals(DOMSource.class)) {
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setNamespaceAware(true);
DocumentBuilder builder = builderFactory.newDocumentBuilder();
InputSource inputSource = null;
if (this.fromResultSet) {
inputSource = new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml));
} else {
inputSource = new InputSource(new StringReader(this.stringRep));
}
return (T) new DOMSource(builder.parse(inputSource));
}
// ...
}
// ...
}
漏洞触发路径
setString方法为stringRep属性赋值getSource方法中未对XML数据进行安全校验- 直接调用
builder.parse解析XML,导致XXE漏洞
漏洞利用场景
直接利用方式
String poc = "<?xml version=\"1.0\" ?>\n" +
"<!DOCTYPE r [\n" +
"<!ELEMENT r ANY >\n" +
"<!ENTITY sp SYSTEM \"http://127.0.0.1:4444/test.txt\">\n" +
"]>\n" +
"<r>&sp;</r>";
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root","xxxxx");
SQLXML sqlxml = connection.createSQLXML();
sqlxml.setString(poc);
sqlxml.getSource(DOMSource.class);
数据库存储利用方式
Connection connection = DriverManager.getConnection("jdbc:mysql://192.168.3.16:3306/test666", "root", "xxxxxxx");
String sql = "SELECT DataXML from config";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
rs.next();
SQLXML xml = rs.getSQLXML("DataXML");
DOMSource = xml.getSource(DOMSource.class);
其他数据库对比分析
SQL Server JDBC处理方式
- DOMSource处理:设置了安全特性防御XXE
factory.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(new SQLServerEntityResolver());
document = builder.parse(this.contents);
- SAXSource处理:未设置安全特性,但SQL Server本身限制DTD使用
Oracle JDBC
未找到对SQLXML的支持,因此不存在此漏洞
修复方案
MySQL JDBC 8.0.27版本中增加了安全防护措施:
DOMSource修复
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setNamespaceAware(true);
setFeature(builderFactory, "http://javax.xml.XMLConstants/feature/secure-processing", true);
setFeature(builderFactory, "http://apache.org/xml/features/disallow-doctype-decl", true);
setFeature(builderFactory, "http://xml.org/sax/features/external-general-entities", false);
setFeature(builderFactory, "http://xml.org/sax/features/external-parameter-entities", false);
setFeature(builderFactory, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
builderFactory.setXIncludeAware(false);
builderFactory.setExpandEntityReferences(false);
builderFactory.setAttribute("http://javax.xml.XMLConstants/property/accessExternalSchema", "");
SAXSource修复
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", true);
setFeature(reader, "http://apache.org/xml/features/disallow-doctype-decl", true);
setFeature(reader, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
setFeature(reader, "http://xml.org/sax/features/external-general-entities", false);
setFeature(reader, "http://xml.org/sax/features/external-parameter-entities", false);
防御建议
- 升级MySQL JDBC驱动至8.0.27或更高版本
- 如果无法升级,可考虑以下措施:
- 避免使用
DOMSource处理不可信的XML数据 - 对数据库中的XML数据进行严格校验
- 使用SAX或StAX解析器替代DOM解析器
- 避免使用
技术背景
SQLXML简介
SQLXML是Java中用于处理数据库XML数据的接口,提供多种形式访问XML值的方法:
getBinaryStream:以流的形式获取XML值getCharacterStream:以Reader对象形式获取XML值getString:返回XML值的字符串表示
XML解析方式对比
| 解析方式 | 特点 | 内存占用 | 是否适合大文件 |
|---|---|---|---|
| DOM | 整个文档加载到内存,形成树结构 | 高 | 不适合 |
| SAX | 基于事件驱动的流式解析 | 低 | 适合 |
| StAX | 基于流的拉式解析 | 低 | 适合 |
总结
MySQL JDBC XXE漏洞主要由于未对XML解析进行安全配置导致,影响8.0.27以下版本。修复方案包括升级驱动或实施严格的数据校验措施。理解不同XML解析方式的特点有助于选择更安全的处理方式。