Bug 63793 - Fix unsecure XML Parsing

This commit is contained in:
pmouawad 2019-10-01 10:45:56 +02:00
parent 8323941eb8
commit d467f5368f
9 changed files with 41 additions and 9 deletions

View File

@ -22,6 +22,8 @@ import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringReader; import java.io.StringReader;
import javax.xml.XMLConstants;
import org.apache.jmeter.samplers.SampleResult; import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.AbstractTestElement; import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.testelement.ThreadListener; import org.apache.jmeter.testelement.ThreadListener;
@ -46,7 +48,9 @@ public class XMLAssertion extends AbstractTestElement implements Serializable, A
@Override @Override
protected XMLReader initialValue() { protected XMLReader initialValue() {
try { try {
return XMLReaderFactory.createXMLReader(); XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
return reader;
} catch (SAXException e) { } catch (SAXException e) {
log.error("Error initializing XMLReader in XMLAssertion", e); log.error("Error initializing XMLReader in XMLAssertion", e);
return null; return null;

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringReader; import java.io.StringReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
@ -102,7 +103,7 @@ public class XMLSchemaAssertion extends AbstractTestElement implements Serializa
parserFactory.setNamespaceAware(true); parserFactory.setNamespaceAware(true);
parserFactory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); parserFactory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
parserFactory.setAttribute(JAXP_SCHEMA_SOURCE, xsdFileName); parserFactory.setAttribute(JAXP_SCHEMA_SOURCE, xsdFileName);
parserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
// create a parser: // create a parser:
DocumentBuilder parser = parserFactory.newDocumentBuilder(); DocumentBuilder parser = parserFactory.newDocumentBuilder();
parser.setErrorHandler(new SAXErrorHandler(result)); parser.setErrorHandler(new SAXErrorHandler(result));

View File

@ -33,6 +33,7 @@ import javax.swing.JMenu;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.MenuElement; import javax.swing.MenuElement;
import javax.xml.XMLConstants;
import javax.xml.transform.Source; import javax.xml.transform.Source;
import javax.xml.transform.Transformer; import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactory;
@ -69,6 +70,7 @@ public class SchematicView extends AbstractAction implements MenuCreator {
throws Exception { throws Exception {
TransformerFactory factory = TransformerFactory.newInstance( TransformerFactory factory = TransformerFactory.newInstance(
"net.sf.saxon.BasicTransformerFactory", Thread.currentThread().getContextClassLoader()); "net.sf.saxon.BasicTransformerFactory", Thread.currentThread().getContextClassLoader());
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Source xslt; Source xslt;
if (!StringUtils.isEmpty(DEFAULT_XSL_FILE)) { if (!StringUtils.isEmpty(DEFAULT_XSL_FILE)) {
log.info("Will use file {} for Schematic View generation", DEFAULT_XSL_FILE); log.info("Will use file {} for Schematic View generation", DEFAULT_XSL_FILE);

View File

@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
@ -167,6 +168,7 @@ public class TemplateManager {
dbf.setNamespaceAware(true); dbf.setNamespaceAware(true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder bd = dbf.newDocumentBuilder(); DocumentBuilder bd = dbf.newDocumentBuilder();
bd.setEntityResolver(new DefaultEntityResolver()); bd.setEntityResolver(new DefaultEntityResolver());
LoggingErrorHandler errorHandler = new LoggingErrorHandler(log, file); LoggingErrorHandler errorHandler = new LoggingErrorHandler(log, file);

View File

@ -29,6 +29,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
@ -65,6 +66,9 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException; import org.xml.sax.SAXParseException;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XPathExecutable; import net.sf.saxon.s9api.XPathExecutable;
@ -72,9 +76,6 @@ import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmItem; import net.sf.saxon.s9api.XdmItem;
import net.sf.saxon.s9api.XdmNode; import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XdmValue; import net.sf.saxon.s9api.XdmValue;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
/** /**
* This class provides a few utility methods for dealing with XML/XPath. * This class provides a few utility methods for dealing with XML/XPath.
*/ */
@ -115,12 +116,13 @@ public class XPathUtil {
* @return javax.xml.parsers.DocumentBuilderFactory * @return javax.xml.parsers.DocumentBuilderFactory
*/ */
private static synchronized DocumentBuilderFactory makeDocumentBuilderFactory(boolean validate, boolean whitespace, private static synchronized DocumentBuilderFactory makeDocumentBuilderFactory(boolean validate, boolean whitespace,
boolean namespace) { boolean namespace) throws ParserConfigurationException {
if (XPathUtil.documentBuilderFactory == null || documentBuilderFactory.isValidating() != validate if (XPathUtil.documentBuilderFactory == null || documentBuilderFactory.isValidating() != validate
|| documentBuilderFactory.isNamespaceAware() != namespace || documentBuilderFactory.isNamespaceAware() != namespace
|| documentBuilderFactory.isIgnoringElementContentWhitespace() != whitespace) { || documentBuilderFactory.isIgnoringElementContentWhitespace() != whitespace) {
// configure the document builder factory // configure the document builder factory
documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
documentBuilderFactory.setValidating(validate); documentBuilderFactory.setValidating(validate);
documentBuilderFactory.setNamespaceAware(namespace); documentBuilderFactory.setNamespaceAware(namespace);
documentBuilderFactory.setIgnoringElementContentWhitespace(whitespace); documentBuilderFactory.setIgnoringElementContentWhitespace(whitespace);
@ -309,7 +311,9 @@ public class XPathUtil {
private static String getNodeContent(Node node) { private static String getNodeContent(Node node) {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
try { try {
Transformer t = TransformerFactory.newInstance().newTransformer(); TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer t = factory.newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.transform(new DOMSource(node), new StreamResult(sw)); t.transform(new DOMSource(node), new StreamResult(sw));
} catch (TransformerException e) { } catch (TransformerException e) {
@ -731,7 +735,9 @@ public class XPathUtil {
*/ */
public static String formatXml(String xml){ public static String formatXml(String xml){
try { try {
Transformer serializer= TransformerFactory.newInstance().newTransformer(); TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer serializer= factory.newTransformer();
serializer.setOutputProperty(OutputKeys.INDENT, "yes"); serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
Source xmlSource = new SAXSource(new InputSource(new StringReader(xml))); Source xmlSource = new SAXSource(new InputSource(new StringReader(xml)));

View File

@ -23,6 +23,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
@ -67,7 +68,9 @@ public class XPathFileContainer {
NodeList nl = null; NodeList nl = null;
try ( FileInputStream fis = new FileInputStream(fileName); try ( FileInputStream fis = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(fis) ){ BufferedInputStream bis = new BufferedInputStream(fis) ){
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder builder = factory.newDocumentBuilder();
nl = XPathUtil.selectNodeList(builder.parse(bis), xpath); nl = XPathUtil.selectNodeList(builder.parse(bis), xpath);
if(log.isDebugEnabled()) { if(log.isDebugEnabled()) {
log.debug("found {}", nl.getLength()); log.debug("found {}", nl.getLength());

View File

@ -25,6 +25,7 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParserFactory;
@ -237,6 +238,7 @@ public class DefaultSamplerCreator extends AbstractSamplerCreator {
private static boolean isPotentialXml(String postData) { private static boolean isPotentialXml(String postData) {
try { try {
SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
SAXParser saxParser = spf.newSAXParser(); SAXParser saxParser = spf.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader(); XMLReader xmlReader = saxParser.getXMLReader();
ErrorDetectionHandler detectionHandler = ErrorDetectionHandler detectionHandler =

View File

@ -92,6 +92,7 @@ class ObjectMessageRenderer implements MessageRenderer<Serializable> {
/** Try to determine encoding based on XML prolog, if none <code>null</code> is returned. **/ /** Try to determine encoding based on XML prolog, if none <code>null</code> is returned. **/
protected String findEncoding(String filename) { protected String findEncoding(String filename) {
XMLInputFactory factory = XMLInputFactory.newInstance(); XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
try (FileInputStream input = new FileInputStream(filename)) { try (FileInputStream input = new FileInputStream(filename)) {
XMLStreamReader reader = factory.createXMLStreamReader(input); XMLStreamReader reader = factory.createXMLStreamReader(input);
return reader.getEncoding(); return reader.getEncoding();

View File

@ -77,6 +77,16 @@ to view the last release notes of version 5.1.1.
<ul> <ul>
<li>HTTP(S) Test Script Recorder now appends number at end of names, while previously it added it at beginning. See <bugzilla>63450</bugzilla></li> <li>HTTP(S) Test Script Recorder now appends number at end of names, while previously it added it at beginning. See <bugzilla>63450</bugzilla></li>
<li>When using XPath Assertion with an XPath expression returning a boolean, <code>True if nothing matches</code> had no effect and always returned true, see <bugzilla>63455</bugzilla></li> <li>When using XPath Assertion with an XPath expression returning a boolean, <code>True if nothing matches</code> had no effect and always returned true, see <bugzilla>63455</bugzilla></li>
<li>XML parsing now refuses unsecure XML, this has impacts on the following features:
<ul>
<li>XMLAssertion</li>
<li>XMLSchemAssertion</li>
<li>XPath function</li>
<li>XPath 1 &amp; 2 Extractors</li>
<li>XPath 1 &amp; 2 Assertions</li>
</ul>
</li>
</ul> </ul>
<!-- =================== Improvements =================== --> <!-- =================== Improvements =================== -->
@ -234,6 +244,7 @@ to view the last release notes of version 5.1.1.
<li><bug>63751</bug>Correct a typo in Chinese translations. Reported by Jinliang Wang (wjl31802 at 126.com)</li> <li><bug>63751</bug>Correct a typo in Chinese translations. Reported by Jinliang Wang (wjl31802 at 126.com)</li>
<li><bug>63723</bug>Distributed testing: JMeter master ends distributed test though some threads still are active</li> <li><bug>63723</bug>Distributed testing: JMeter master ends distributed test though some threads still are active</li>
<li><bug>63614</bug>Distributed testing: Unable to generate Dashboard report at end of load test</li> <li><bug>63614</bug>Distributed testing: Unable to generate Dashboard report at end of load test</li>
<li><bug>63793</bug>Fix unsecure XML Parsing</li>
</ul> </ul>
<!-- =================== Thanks =================== --> <!-- =================== Thanks =================== -->