From 1853361e9f49f6b04aa5cd9ead85cf4620d4d249 Mon Sep 17 00:00:00 2001 From: Christine Poerschke Date: Fri, 13 Oct 2017 12:46:58 +0100 Subject: [PATCH] SOLR-11477: Disallow resolving of external entities in Lucene queryparser/xml/CoreParser and SolrCoreParser (defType=xmlparser or {!xmlparser ...}) by default. (Michael Stepankin, Olga Barinova, Uwe Schindler, Christine Poerschke) --- .../apache/lucene/xmlparser/CoreParser.java | 74 +++++++++++++++---- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/CoreParser.java b/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/CoreParser.java index c84b90a..68c1529 100644 --- a/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/CoreParser.java +++ b/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/CoreParser.java @@ -1,9 +1,12 @@ package org.apache.lucene.xmlparser; import java.io.InputStream; +import java.util.Locale; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.queryParser.QueryParser; @@ -11,6 +14,10 @@ import org.apache.lucene.search.Query; import org.apache.lucene.xmlparser.builders.*; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.InputSource; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -123,7 +130,11 @@ public class CoreParser implements QueryBuilder sqof.addBuilder("SpanNot",snot); queryFactory.addBuilder("SpanNot",snot); } - + + /** + * Parses the given stream as XML file and returns a {@link Query}. + * By default this disallows external entities for security reasons. + */ public Query parse(InputStream xmlStream) throws ParserException { return getQuery(parseXML(xmlStream).getDocumentElement()); @@ -138,28 +149,49 @@ public class CoreParser implements QueryBuilder filterFactory.addBuilder(nodeName,builder); } - private static Document parseXML(InputStream pXmlFile) throws ParserException - { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = null; + /** + * Returns a SAX {@link EntityResolver} to be used by {@link DocumentBuilder}. + * By default this returns {@link #DISALLOW_EXTERNAL_ENTITY_RESOLVER}, which disallows the + * expansion of external entities (for security reasons). To restore legacy behavior, + * override this method to return {@code null}. + */ + protected EntityResolver getEntityResolver() { + return DISALLOW_EXTERNAL_ENTITY_RESOLVER; + } + + /** + * Subclass and override to return a SAX {@link ErrorHandler} to be used by {@link DocumentBuilder}. + * By default this returns {@code null} so no error handler is used. + * This method can be used to redirect XML parse errors/warnings to a custom logger. + */ + protected ErrorHandler getErrorHandler() { + return null; + } + + private Document parseXML(InputStream pXmlFile) throws ParserException { + final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setValidating(false); try { - db = dbf.newDocumentBuilder(); - } - catch (Exception se) - { - throw new ParserException("XML Parser configuration error", se); + dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException e) { + // ignore since all implementations are required to support the + // {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature } - org.w3c.dom.Document doc = null; + final DocumentBuilder db; try { - doc = db.parse(pXmlFile); + db = dbf.newDocumentBuilder(); + } catch (Exception se) { + throw new ParserException("XML Parser configuration error.", se); } - catch (Exception se) - { - throw new ParserException("Error parsing XML stream:" + se, se); + try { + db.setEntityResolver(getEntityResolver()); + db.setErrorHandler(getErrorHandler()); + return db.parse(pXmlFile); + } catch (Exception se) { + throw new ParserException("Error parsing XML stream: " + se, se); } - return doc; } @@ -167,4 +199,14 @@ public class CoreParser implements QueryBuilder { return queryFactory.getQuery(e); } + + public static final EntityResolver DISALLOW_EXTERNAL_ENTITY_RESOLVER = new EntityResolver() { + @Override + public InputSource resolveEntity(String publicId, String systemId) throws SAXException { + throw new SAXException(String.format(Locale.ENGLISH, + "External Entity resolving unsupported: publicId=\"%s\" systemId=\"%s\"", + publicId, systemId)); + } + }; + } -- 2.23.0