1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.xml.secure;
19
20 import javax.xml.XMLConstants;
21 import javax.xml.parsers.DocumentBuilderFactory;
22 import javax.xml.transform.TransformerFactory;
23 import javax.xml.validation.SchemaFactory;
24
25 import org.junit.jupiter.api.Assumptions;
26 import org.junit.jupiter.api.Tag;
27 import org.junit.jupiter.api.Test;
28 import org.xml.sax.XMLReader;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 class AccessExternalPropertyTest {
47
48 private static final String INSERTION = "&leaked;";
49
50 private static String withDoctype(final String rootQName, final String body) {
51 return "<?xml version=\"1.0\"?>\n"
52 + "<!DOCTYPE " + rootQName + " SYSTEM \"" + AttackTestSupport.resourceUrl("referenced.dtd") + "\">\n"
53 + body + "\n";
54 }
55
56 private static String xmlPayload() {
57 return withDoctype("root", AttackTestSupport.xmlBody(INSERTION));
58 }
59
60 private static String xsdPayload() {
61 return withDoctype("xs:schema", AttackTestSupport.xsdBody(INSERTION));
62 }
63
64 @Test
65 @Tag("dom")
66 void secureDomWithAccessExternalAllDoesNotLeak() {
67 Assumptions.assumeTrue(AttackTestSupport.DOM_RESOLVES_INTERNAL_ENTITIES,
68 "Skipped: platform DOM does not resolve user-defined entities");
69 final DocumentBuilderFactory factory = SecureDocumentBuilderFactory.newInstance();
70 AttackTestSupport.assumeDoesNotThrow(() -> factory.setAttribute(TestConstants.ACCESS_EXTERNAL_DTD, "all"));
71 AttackTestSupport.assertDomDoesNotLeak(factory, xmlPayload());
72 }
73
74 @Test
75 @Tag("sax")
76 void secureSaxWithAccessExternalAllDoesNotLeak() throws Exception {
77 final XMLReader reader = SecureSAXParserFactory.newInstance().newSAXParser().getXMLReader();
78 AttackTestSupport.assumeDoesNotThrow(() -> reader.setProperty(TestConstants.ACCESS_EXTERNAL_DTD, "all"));
79 AttackTestSupport.assertSaxDoesNotLeak(reader, xmlPayload());
80 }
81
82 @Test
83 @Tag("schema")
84 void secureSchemaDoctypeWithAccessExternalAllDoesNotLeak() {
85 final SchemaFactory factory = SecureSchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
86 AttackTestSupport.assumeDoesNotThrow(() -> factory.setProperty(TestConstants.ACCESS_EXTERNAL_DTD, "all"));
87 AttackTestSupport.assertSchemaDoesNotLeak(factory, AttackTestSupport.streamSource(xsdPayload()));
88 }
89
90 @Test
91 @Tag("schema")
92 void secureSchemaImportWithAccessExternalAllBlocks() {
93 final SchemaFactory factory = SecureSchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
94 AttackTestSupport.assumeDoesNotThrow(() -> factory.setProperty(TestConstants.ACCESS_EXTERNAL_SCHEMA, "all"));
95 AttackTestSupport.assertSchemaBlocks(factory, AttackTestSupport.resourceSource("with-import.xsd"));
96 }
97
98 @Test
99 @Tag("trax")
100 void secureTemplatesImportWithAccessExternalAllDoesNotLeak() {
101 final TransformerFactory factory = SecureTransformerFactory.newInstance();
102 AttackTestSupport.assumeDoesNotThrow(() -> factory.setAttribute(TestConstants.ACCESS_EXTERNAL_STYLESHEET, "all"));
103 AttackTestSupport.assertTemplatesDoesNotLeak(factory, AttackTestSupport.resourceSource("with-import.xsl"));
104 }
105
106 @Test
107 @Tag("trax")
108 void secureTransformerDoctypeWithAccessExternalAllDoesNotLeak() {
109 final TransformerFactory factory = SecureTransformerFactory.newInstance();
110 AttackTestSupport.assumeDoesNotThrow(() -> factory.setAttribute(TestConstants.ACCESS_EXTERNAL_DTD, "all"));
111 AttackTestSupport.assertTransformerDoesNotLeak(factory, xmlPayload());
112 }
113 }