Bug 64541

Summary: Parsing of mbeans-descriptor.xml files throw errors on server startup
Product: Tomcat 7 Reporter: Valentin Dimitrov <vdimitrov>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: regression    
Priority: P2    
Version: 7.0.104   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Attachments: The tomcat startup server log

Description Valentin Dimitrov 2020-06-19 15:40:50 UTC
Created attachment 37319 [details]
The tomcat startup server log

I'm using tomcat version 7.0.104 on a linux system. 
The JVM used is Adopt's OpenJDK 11. 

When starting the server, the logs are full of errors regarding all the mbeans-descriptor.xml files in the catalina.jar and jasper.jar archives. The errors are regarding the entity expansion limit for jaxp, which in our case is 1 (for security reasons). This error is a regression from version 7.0.104(since we don't have this problem with 7.0.103) and is probably caused from adding of this verification against mbeans-descriptor.dtd: https://github.com/apache/tomcat/commit/1f1877c3d888f519f0544386cebc3c3f0ca16786 .
I'm attaching a part of the tomcat logs, which contains the stacktrace of the error.
Comment 1 Christopher Schultz 2020-06-19 20:32:10 UTC
Interesting.

How are you setting the limit for the JAXP entity expansion... via the system property "jdk.xml.entityExpansionLimit"?

What's the security justification for the setting of "1" and not, say, 3 or 5 or 63999?

Do you happen to know if the system property will override explicitly-setting the JAXP feature "http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit"? I don't have a test-case handy and if you happen to know the answer it might get us to a solution more quickly.
Comment 2 Valentin Dimitrov 2020-06-22 09:31:56 UTC
We're setting the entityExpansionLimit in a jaxp.properties file under '/jre/conf/'.

Our product relies on security and the code scanners of our clients require us to use the value 1, which with the current version 7.0.104 of Tomcat is impossible.Тhe minimum value, in order to resolve the errors in the log, for the property is 20, which in all cases can't be good (Billion laughs and possible denial of service is possible with a value of 10).

We checked the property and it seems that the system property overrides the jaxp.properties file.
Comment 3 Christopher Schultz 2020-06-22 17:03:22 UTC
Odd. I'm unsure why you'd need an entity expansion depth of 20 to get it to work, especially since http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd ultimately leads to a 404 response so... no entities defined there!

Something seems fishy, here.
Comment 4 Christopher Schultz 2020-06-22 17:10:20 UTC
(In reply to Christopher Schultz from comment #3)
> Something seems fishy, here.

Oh, duh. Tomcat supplies its own copy of mbeans-descriptors.dtd which is used. And it's got a handful of entities defined.
Comment 5 Christopher Schultz 2020-06-22 17:29:23 UTC
I was able to reproduce this on Tomcat 8.5.56 using:

$ export CATALINA_OPTS=-Djdk.xml.entityExpansionLimit=1
$ $CATALINA_HOME/bin/catalina.sh run

I needed to raise the limit to 17 in order to get the parsing to succeed.

This is very surprising to me: this DTD only contains a single level of entity-definitions.
Comment 6 Christopher Schultz 2020-06-22 17:48:24 UTC
I was able to work around this by adding the following line of code to MbeansDescriptorsDigesterSource.createDigester() method:

    digester.getParser().setProperty("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit", 20);

This actually subverts your security settings, however.

I'm still curious as to why the SAX parser is warning of deep entity replacements, here, when I only see a single level.
Comment 7 Christopher Schultz 2020-06-22 17:57:53 UTC
(In reply to Christopher Schultz from comment #6)
> I'm still curious as to why the SAX parser is warning of deep entity
> replacements, here, when I only see a single level.

Another "duh": this isn't about limits on entity expansion depth. Just the expansion *count*.

So if you have a document like this:

<!ENTITY foo "bar">

&foo;
&foo;
&foo;
&foo;
&foo;

You'll need to have an entityExpansionLimit of 5 or more in order to allow the document to be parsed without error.

This has nothing to do with the billion laughs attack, except that entityExpansionLimit can be used to limit the total number of replacements (which indeed can effectively mitigate the billion-laughs attack). By limiting the number of replacements to "1" you are effectively disabling all use of XML entities, which isn't really practical.

I think the JAXP security settings you are looking for are more like these:

XMLConstants.FEATURE_SECURE_PROCESSING
http://xml.org/sax/features/external-general-entities
http://xml.org/sax/features/external-parameter-entities

I'm not convinced Tomcat should fix this bug, yet, but if Tomcat does fix this, it will be by explicitly-allowing entity expansion when parsing its own files, which may be a violation of the security policies which your organization sets.

I'm not sure if there is a good solution, here, for you, other than removing the DOCTYPE definitions.
Comment 8 Mark Thomas 2020-06-22 22:49:19 UTC
Could we provide a DTD where those entities have already been expanded? We could add a comment in the defined types section to explain what was done and why.
Comment 9 Mark Thomas 2020-06-22 22:49:53 UTC
When I say provide, I mean replace the version Tomcat currently ships with.
Comment 10 Christopher Schultz 2020-06-23 16:08:01 UTC
Modifying our existing (copy of) DTD is definitely an option. None of the J*EE DTDs are parsable without entity-expansion, either, though. I haven't pulled-down the entire tree of schemas recently, but I thought at some point they themselves relied on entity-expansion as well.
Comment 11 Mark Thomas 2020-06-29 16:53:56 UTC
I went with the option of manually expanding the entities. There weren't that many.

Fixed in:
- master for 10.0.0-M7 onwards
- 9.0.x for 9.0.37 onwards
- 8.5.x for 8.5.57 onwards
- 7.0.x for 7.0.105 onwards