Hello Jochen,

In our application there is definitely a security issue, and I know for a fact that it can be solved by setting the features http://xml.org/sax/features/external-general-entities and http://xml.org/sax/features/external-parameter-entities to false for the SAX parser (I have tested it). I have provided a patch for the org.apache.xmlrpc.util.SAXParsers class, unfortunately I forgot to attach it to my first mail, if you haven't received it I'll attach it to this mail as well.

By including the external entity inside a <i4> element like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE OBJECTS [<!ENTITY test SYSTEM "c:\boot.ini">]>
...
<i4>9701&test;</i4>
...

It will cause a number format exception when trying to parse the text "9701&test;" as an integer (I believe this exception is thrown by org.apache.xmlrpc.server.XmlRpcStreamServer.getRequest, please see the attached stack trace). The reason it becomes a security issue for us is that we send back an error response that includes the error message from the exception (see attachment). Whether this information should be included in the response or not is maybe debatable but I'm sure we are not the only ones including this kind of information in the response and because of this I think it is a security issue. In this example I have used "c:\boot.ini" as the exposed file, and it may not be so sensitive but I'm sure that for instance "c:\program files\tomcat\conf\tomcat-users.xml" would be a much more interesting file.

The patch I have suggested doesn't affect anyone who doesn't like to use the new functionality and I have a hard time seeing the harm in letting developers set features for the SAX parser used by XML-RPC.


Best regards
Johan


Jochen Wiedmann wrote:
Hi, Johan,

lets distinguish between two different questions:

- Whether there is a security issue. If so, this is of course of
general interest and ought to be fixed immediately.

I can imagine that you include an external entity into the clients
message. I can also imagine that this adds a local files contents to
the request. However, I have difficulties to understand why this
should become a part of the response? Is this specific to your
application?

- Whether and how you'd like to access the SAX parser.

Give me a few days to think about this.


Jochen

On Wed, Feb 3, 2010 at 11:23 AM, Johan Hägre <johan.ha...@home.se> wrote:
I should of course attach the patch as well, sorry.

This is the first time I'm submitting a patch, so I'm hoping this is the
right way to do it.

In our use of XML-RPC we have discovered a security issue regarding the use
of external entities in XML. By creating a custom XML message and sending it
to the XML-RPC handling service it is possible to get the contents of files
stored on the server's file system as part of the response. The way we would
like to solve this is to set the features
http://xml.org/sax/features/external-general-entities and
http://xml.org/sax/features/external-parameter-entities to false for the SAX
parser. However we have not been able to find a way to set this since we
can't get hold of the parser object. The solution we propose is to add a way
to set features in the org.apache.xmlrpc.util.SAXParsers class. The features
set here will be used for all XMLReaders created through subsequent calls to
SAXParsers.newXMLReader(). This modification will not affect any existing
application since if the setFeature() method in the SAXParsers class isn't
used nothing will happen. The patch file (created using svn diff) is
attached to this post.


Best regards
Johan Hägre




Index: SAXParsers.java
===================================================================
--- SAXParsers.java     (revision 905923)
+++ SAXParsers.java     (arbetskopia)
@@ -23,6 +23,8 @@

 import org.apache.xmlrpc.XmlRpcException;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
 import org.xml.sax.XMLReader;


@@ -36,6 +38,14 @@
               spf.setValidating(false);
       }

+       public static void setFeature(String pName, boolean pValue) throws
SAXNotRecognizedException, SAXNotSupportedException,
ParserConfigurationException {
+               spf.setFeature(pName, pValue);
+       }
+
+       public static boolean getFeature(String pName) throws
SAXNotRecognizedException, SAXNotSupportedException,
ParserConfigurationException {
+               return spf.getFeature(pName);
+       }
+
       /** Creates a new instance of {...@link XMLReader}.
        */
       public static XMLReader newXMLReader() throws XmlRpcException {





2010-02-03 16:30:05,687 ERROR http-8443-Processor25 
org.apache.xmlrpc.server.XmlRpcErrorLogger - Failed to parse XML-RPC request: 
Failed to parse integer value: 9701[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Microsoft Windows XP Professional" 
/noexecute=optin /fastdetect

org.apache.xmlrpc.XmlRpcException: Failed to parse XML-RPC request: Failed to 
parse integer value: 9701[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Microsoft Windows XP Professional" 
/noexecute=optin /fastdetect

        at 
org.apache.xmlrpc.server.XmlRpcStreamServer.getRequest(XmlRpcStreamServer.java:71)
        at 
org.apache.xmlrpc.server.XmlRpcStreamServer.execute(XmlRpcStreamServer.java:199)
        at 
org.apache.xmlrpc.webserver.XmlRpcServletServer.execute(XmlRpcServletServer.java:112)
        at 
se._4cs.exonaut.servlet.ExonautXmlRpcServlet.doPost(ExonautXmlRpcServlet.java:100)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
        at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
        at 
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
        at 
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
        at 
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
        at 
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at 
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
        at 
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
        at 
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
        at 
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
        at 
org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
        at 
org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
        at 
org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
        at 
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
        at java.lang.Thread.run(Unknown Source)
Caused by: org.xml.sax.SAXParseException: Failed to parse integer value: 
9701[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Microsoft Windows XP Professional" 
/noexecute=optin /fastdetect

        at org.apache.xmlrpc.parser.I4Parser.setResult(I4Parser.java:32)
        at 
org.apache.xmlrpc.parser.AtomicParser.endElement(AtomicParser.java:59)
        at 
org.apache.xmlrpc.parser.RecursiveTypeParserImpl.endElement(RecursiveTypeParserImpl.java:103)
        at org.apache.xmlrpc.parser.MapParser.endElement(MapParser.java:193)
        at 
org.apache.xmlrpc.parser.RecursiveTypeParserImpl.endElement(RecursiveTypeParserImpl.java:103)
        at 
org.apache.xmlrpc.parser.XmlRpcRequestParser.endElement(XmlRpcRequestParser.java:165)
        at 
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(Unknown 
Source)
        at 
com.sun.org.apache.xerces.internal.impl.dtd.XMLNSDTDValidator.endNamespaceScope(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.handleEndElement(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.endElement(Unknown 
Source)
        at 
com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown 
Source)
        at 
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown 
Source)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown 
Source)
        at 
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown 
Source)
        at 
org.apache.xmlrpc.server.XmlRpcStreamServer.getRequest(XmlRpcStreamServer.java:65)
        ... 20 more
Caused by:
org.xml.sax.SAXParseException: Failed to parse integer value: 9701[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Microsoft Windows XP Professional" 
/noexecute=optin /fastdetect

        at org.apache.xmlrpc.parser.I4Parser.setResult(I4Parser.java:32)
        at 
org.apache.xmlrpc.parser.AtomicParser.endElement(AtomicParser.java:59)
        at 
org.apache.xmlrpc.parser.RecursiveTypeParserImpl.endElement(RecursiveTypeParserImpl.java:103)
        at org.apache.xmlrpc.parser.MapParser.endElement(MapParser.java:193)
        at 
org.apache.xmlrpc.parser.RecursiveTypeParserImpl.endElement(RecursiveTypeParserImpl.java:103)
        at 
org.apache.xmlrpc.parser.XmlRpcRequestParser.endElement(XmlRpcRequestParser.java:165)
        at 
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(Unknown 
Source)
        at 
com.sun.org.apache.xerces.internal.impl.dtd.XMLNSDTDValidator.endNamespaceScope(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.handleEndElement(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.endElement(Unknown 
Source)
        at 
com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown
 Source)
        at 
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown 
Source)
        at 
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown 
Source)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown 
Source)
        at 
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown 
Source)
        at 
org.apache.xmlrpc.server.XmlRpcStreamServer.getRequest(XmlRpcStreamServer.java:65)
        at 
org.apache.xmlrpc.server.XmlRpcStreamServer.execute(XmlRpcStreamServer.java:199)
        at 
org.apache.xmlrpc.webserver.XmlRpcServletServer.execute(XmlRpcServletServer.java:112)
        at 
se._4cs.exonaut.servlet.ExonautXmlRpcServlet.doPost(ExonautXmlRpcServlet.java:100)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
        at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
        at 
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
        at 
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
        at 
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
        at 
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at 
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
        at 
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
        at 
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
        at 
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
        at 
org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
        at 
org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
        at 
org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
        at 
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
        at java.lang.Thread.run(Unknown Source)
<?xml version="1.0" 
encoding="UTF-8"?><methodResponse><fault><value><struct><member><name>faultString</name><value>Failed
 to parse XML-RPC request: Failed to parse integer value: 9701[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Microsoft Windows XP Professional" 
/noexecute=optin /fastdetect
</value></member><member><name>faultCode</name><value><i4>0</i4></value></member></struct></value></fault></methodResponse>
Index: SAXParsers.java
===================================================================
--- SAXParsers.java     (revision 905923)
+++ SAXParsers.java     (arbetskopia)
@@ -23,6 +23,8 @@
 
 import org.apache.xmlrpc.XmlRpcException;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
 import org.xml.sax.XMLReader;
 
 
@@ -36,6 +38,14 @@
                spf.setValidating(false);
        }
 
+       public static void setFeature(String pName, boolean pValue) throws 
SAXNotRecognizedException, SAXNotSupportedException, 
ParserConfigurationException {
+               spf.setFeature(pName, pValue);
+       }
+       
+       public static boolean getFeature(String pName) throws 
SAXNotRecognizedException, SAXNotSupportedException, 
ParserConfigurationException {
+               return spf.getFeature(pName);
+       }
+       
        /** Creates a new instance of {...@link XMLReader}.
         */
        public static XMLReader newXMLReader() throws XmlRpcException {

Reply via email to