Piotr Karwasz created KNOX-3484:
-----------------------------------
Summary: Use Apache Commons Secure XML for all JAXP factories
Key: KNOX-3484
URL: https://issues.apache.org/jira/browse/KNOX-3484
Project: Apache Knox
Issue Type: Improvement
Reporter: Piotr Karwasz
Knox configures its XML parsers by hand. Every call site that creates a JAXP
factory repeats its own subset of features and properties
({{{}disallow-doctype-decl{}}}, {{{}FEATURE_SECURE_PROCESSING{}}},
{{{}SUPPORT_DTD{}}}, {{{}isSupportingExternalEntities{}}},
{{{}ACCESS_EXTERNAL_*{}}}, ...), and the subsets differ from site to site. Some
sites set nothing and rely on the defaults of whichever implementation (JDK,
Woodstox, MOXy, Glassfish JAXB, Commons Digester) happens to serve them. Some
ignore a failure to apply a setting.
Keeping this correct is a recurring cost for the PMC: every new parser has to
remember the full list, several of the feature names are
implementation-specific, and whether a given setting takes effect depends on
which implementation serves which call site.
[Apache Commons Secure
XML|https://commons.apache.org/proper/commons-secure-xml/] (1.0.0, Java 8+, no
runtime dependencies, Apache-2.0) moves that work into one dependency. Its
factories are hardened as delivered: external resources (DTDs, external
entities, XInclude, schema imports, stylesheets) are ignored by non-removable
resolvers, independently of the underlying JAXP implementation, and a factory
that cannot be hardened fails loudly instead of silently. The guarantees are
documented in its [threat
model|https://commons.apache.org/proper/commons-secure-xml/threat_model.html]
and tested against the JDK, Xerces, Woodstox and Saxon.
This is a hardening and maintenance change: it replaces the ad hoc
configuration with one consistent dependency, so that the PMC no longer has to
configure XML parsers.
h2. Current state
||Module||Class||API||Current configuration||
|gateway-util-common|{{XmlUtils}} ({{{}readXml{}}}, {{{}createDocument{}}},
{{{}getTransformer{}}})|DOM, TrAX|{{{}FEATURE_SECURE_PROCESSING{}}},
{{disallow-doctype-decl}}|
|gateway-service-admin|{{{}ServiceDefinitionUnmarshaller{}}},
{{TopologyMarshaller}}|StAX + JAXB|{{{}SUPPORT_DTD{}}},
{{{}isSupportingExternalEntities{}}}, {{isReplacingEntityReferences}}|
|gateway-provider-rewrite|{{XmlFilterReader}}|StAX, XPath|StAX: same three
properties; XPath: {{{}FEATURE_SECURE_PROCESSING{}}}, failure ignored|
|gateway-discovery-ambari|{{ServiceURLPropertyConfig}}|XPath|none|
|gateway-server|{{TopologyValidator}}|Validation|{{ACCESS_EXTERNAL_*}} on the
{{Validator}} only|
|gateway-spi|{{UrlRewriteRulesDescriptorAdapter}}|TrAX|none|
|gateway-server|{{{}ServiceDefinitionsLoader{}}},
{{{}ApplicationDeploymentContributor{}}}, {{TopologyToDescriptor}}|JAXB
{{unmarshal(File/InputStream)}}|none (depends on the JAXB provider)|
|gateway-service-remoteconfig|{{RemoteConfigurationRegistriesParser}}|JAXB
{{unmarshal(File)}}|none (depends on the JAXB provider)|
|gateway-topology-simple|{{ProviderConfigurationParser}}|JAXB
{{unmarshal(InputStream)}}|none (depends on the JAXB provider)|
|gateway-server, gateway-provider-rewrite-common|{{{}TopologyUtils{}}},
{{{}XmlGatewayDescriptorImporter{}}}, {{XmlUrlRewriteRulesImporter}}|Commons
Digester|none (depends on Digester's {{{}SAXParserFactory{}}})|
h2. Proposed changes
Add {{org.apache.commons:commons-secure-xml}} to the root
{{dependencyManagement}} and to the modules above, then:
* *DOM and TrAX:* {{XmlUtils}} and {{UrlRewriteRulesDescriptorAdapter}} obtain
their factories from {{SecureDocumentBuilderFactory}} and
{{{}SecureTransformerFactory{}}}. The security-motivated feature settings are
removed; {{disallow-doctype-decl}} may be kept where Knox prefers to reject a
DOCTYPE outright, as a behavioral choice rather than a security setting.
* *StAX:* {{{}ServiceDefinitionUnmarshaller{}}}, {{TopologyMarshaller}} and
{{XmlFilterReader}} obtain their {{XMLInputFactory}} from
{{{}SecureXMLInputFactory.newFactory(){}}}. {{SUPPORT_DTD=false}} may likewise
be kept as a behavioral choice: Commons Secure XML accepts settings that
restrict further.
* *XPath:* {{XmlFilterReader}} and {{ServiceURLPropertyConfig}} use
{{{}SecureXPathFactory{}}}.
* *Validation:* {{TopologyValidator}} uses {{{}SecureSchemaFactory{}}}.
* *JAXB:* the {{unmarshal(File)}} and {{unmarshal(InputStream)}} calls are
replaced with {{{}unmarshal(XMLEventReader){}}}, where the reader is created by
{{{}SecureXMLInputFactory.newFactory().createXMLEventReader(...){}}}. The
hardening then no longer depends on which JAXB provider (MOXy or the Glassfish
runtime) serves a given context.
* *Commons Digester:* the next Digester release depends on Commons Secure XML
and hardens its parser by default, so upgrading Digester brings the same
protection and the dependency comes at no extra cost. Until then, the three
importers can pass a hardened reader explicitly:
{{{}DigesterLoader.newDigester(SecureSAXParserFactory.newNSInstance().newSAXParser().getXMLReader(),
rules){}}}.
h2. Enforcement
To keep raw factories from coming back, add a
[forbidden-apis|https://github.com/policeman-tools/forbidden-apis] check with a
signatures file that rejects the plain JAXP factory methods
({{{}DocumentBuilderFactory{}}}, {{{}SAXParserFactory{}}},
{{{}XMLInputFactory{}}}, {{{}TransformerFactory{}}}, {{{}SchemaFactory{}}},
{{{}XPathFactory{}}}) and the {{unmarshal(File)}} / {{unmarshal(InputStream)}}
overloads of {{jakarta.xml.bind.Unmarshaller}} in main code.
No new XXE tests are needed: the guarantees are the library's and are tested
there. The existing KNOX-1308 and KNOX-3447 tests should keep passing unchanged.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)