File: CVE-2021-40690.patch

package info (click to toggle)
libxml-security-java 2.0.10-2%2Bdeb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 18,580 kB
  • sloc: java: 79,891; xml: 23,784; sh: 235; makefile: 8
file content (347 lines) | stat: -rw-r--r-- 18,263 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
From: Markus Koschany <apo@debian.org>
Date: Sun, 14 Nov 2021 18:59:23 +0100
Subject: CVE-2021-40690

Bug-Debian: https://bugs.debian.org/994569
Origin: https://github.com/apache/santuario-xml-security-java/commit/56ec2160c161c6bc41e5c297eed077e8ecece312
Origin: https://github.com/apache/santuario-xml-security-java/commit/c3410a7fbecaa7dca61361d887f801b9e6c66c15
---
 .../xml/dsig/internal/dom/DOMURIDereferencer.java  | 23 ++++++++++++---------
 .../xml/security/encryption/XMLCipherInput.java    | 13 +++++++++---
 .../implementations/KeyInfoReferenceResolver.java  | 15 +++++++++++---
 .../implementations/RetrievalMethodResolver.java   | 24 ++++++++++++++--------
 .../security/resource/xmlsecurity_en.properties    |  3 ++-
 .../xml/security/signature/XMLSignatureInput.java  |  2 +-
 .../transforms/implementations/TransformXPath.java |  6 +-----
 .../security/utils/resolver/ResourceResolver.java  | 24 ++++++++++++++++++++++
 .../crypto/test/dsig/CreateBaltimore23Test.java    |  1 +
 .../keyresolver/KeyInfoReferenceResolverTest.java  | 22 ++++++++++++++++++++
 .../KeyInfoReference-RSA-RetrievalMethod.xml       | 22 ++++++++++++++++++++
 11 files changed, 124 insertions(+), 31 deletions(-)
 create mode 100644 src/test/resources/org/apache/xml/security/keyresolver/KeyInfoReference-RSA-RetrievalMethod.xml

diff --git a/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java b/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
index 1d7be4d..bbde878 100644
--- a/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
+++ b/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
@@ -106,17 +106,20 @@ public final class DOMURIDereferencer implements URIDereferencer {
             }
         }
 
-        try {
-            ResourceResolver apacheResolver =
-                ResourceResolver.getInstance(uriAttr, baseURI, secVal);
-            XMLSignatureInput in = apacheResolver.resolve(uriAttr, baseURI, secVal);
-            if (in.isOctetStream()) {
-                return new ApacheOctetStreamData(in);
-            } else {
-                return new ApacheNodeSetData(in);
+        if (uriRef instanceof javax.xml.crypto.dsig.Reference || ResourceResolver.isURISafeToResolve(uriAttr, baseURI)) {
+            try {
+                ResourceResolver apacheResolver =
+                        ResourceResolver.getInstance(uriAttr, baseURI, secVal);
+                XMLSignatureInput in = apacheResolver.resolve(uriAttr, baseURI, secVal);
+                if (in.isOctetStream()) {
+                    return new ApacheOctetStreamData(in);
+                } else {
+                    return new ApacheNodeSetData(in);
+                }
+            } catch (Exception e) {
+                throw new URIReferenceException(e);
             }
-        } catch (Exception e) {
-            throw new URIReferenceException(e);
         }
+        throw new URIReferenceException("URI " + uri + " is forbidden");
     }
 }
diff --git a/src/main/java/org/apache/xml/security/encryption/XMLCipherInput.java b/src/main/java/org/apache/xml/security/encryption/XMLCipherInput.java
index 003b402..87d2ac9 100644
--- a/src/main/java/org/apache/xml/security/encryption/XMLCipherInput.java
+++ b/src/main/java/org/apache/xml/security/encryption/XMLCipherInput.java
@@ -127,9 +127,16 @@ public class XMLCipherInput {
             XMLSignatureInput input = null;
 
             try {
-                ResourceResolver resolver =
-                    ResourceResolver.getInstance(uriAttr, null, secureValidation);
-                input = resolver.resolve(uriAttr, null, secureValidation);
+                if (ResourceResolver.isURISafeToResolve(uriAttr, null)) {
+                    ResourceResolver resolver =
+                            ResourceResolver.getInstance(uriAttr, null, secureValidation);
+                    input = resolver.resolve(uriAttr, null, secureValidation);
+                } else {
+                    String uriToResolve = uriAttr != null ? uriAttr.getValue() : null;
+                    Object[] exArgs = {uriToResolve != null ? uriToResolve : "null", null};
+
+                    throw new ResourceResolverException("utils.resolver.noClass", exArgs, uriToResolve, null);
+                }
             } catch (ResourceResolverException ex) {
                 throw new XMLEncryptionException(ex);
             }
diff --git a/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java b/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java
index d0dae9b..4f3a63f 100644
--- a/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java
+++ b/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java
@@ -38,6 +38,7 @@ import org.apache.xml.security.signature.XMLSignatureInput;
 import org.apache.xml.security.utils.Constants;
 import org.apache.xml.security.utils.XMLUtils;
 import org.apache.xml.security.utils.resolver.ResourceResolver;
+import org.apache.xml.security.utils.resolver.ResourceResolverException;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
@@ -197,6 +198,7 @@ public class KeyInfoReferenceResolver extends KeyResolverSpi {
         validateReference(referentElement);
 
         KeyInfo referent = new KeyInfo(referentElement, baseURI);
+        referent.setSecureValidation(secureValidation);
         referent.addStorageResolver(storage);
         return referent;
     }
@@ -215,7 +217,7 @@ public class KeyInfoReferenceResolver extends KeyResolverSpi {
         }
 
         KeyInfo referent = new KeyInfo(referentElement, "");
-        if (referent.containsKeyInfoReference()) {
+        if (referent.containsKeyInfoReference() || referent.containsRetrievalMethod()) {
             if (secureValidation) {
                 throw new XMLSecurityException("KeyInfoReferenceResolver.InvalidReferentElement.ReferenceWithSecure");
             } else {
@@ -239,8 +241,15 @@ public class KeyInfoReferenceResolver extends KeyResolverSpi {
      */
     private XMLSignatureInput resolveInput(Attr uri, String baseURI, boolean secureValidation)
         throws XMLSecurityException {
-        ResourceResolver resRes = ResourceResolver.getInstance(uri, baseURI, secureValidation);
-        return resRes.resolve(uri, baseURI, secureValidation);
+        if (ResourceResolver.isURISafeToResolve(uri, baseURI)) {
+            ResourceResolver resRes = ResourceResolver.getInstance(uri, baseURI, secureValidation);
+            return resRes.resolve(uri, baseURI, secureValidation);
+        }
+
+        String uriToResolve = uri != null ? uri.getValue() : null;
+        Object[] exArgs = { uriToResolve != null ? uriToResolve : "null", baseURI };
+
+        throw new ResourceResolverException("utils.resolver.noClass", exArgs, uriToResolve, baseURI);
     }
 
     /**
diff --git a/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java b/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java
index 811dcc6..a528e0f 100644
--- a/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java
+++ b/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java
@@ -45,6 +45,7 @@ import org.apache.xml.security.transforms.Transforms;
 import org.apache.xml.security.utils.Constants;
 import org.apache.xml.security.utils.XMLUtils;
 import org.apache.xml.security.utils.resolver.ResourceResolver;
+import org.apache.xml.security.utils.resolver.ResourceResolverException;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -299,15 +300,22 @@ public class RetrievalMethodResolver extends KeyResolverSpi {
         Attr uri = rm.getURIAttr();
         // Apply the transforms
         Transforms transforms = rm.getTransforms();
-        ResourceResolver resRes = ResourceResolver.getInstance(uri, baseURI, secureValidation);
-        XMLSignatureInput resource = resRes.resolve(uri, baseURI, secureValidation);
-        if (transforms != null) {
-            if (log.isDebugEnabled()) {
-                log.debug("We have Transforms");
+        if (ResourceResolver.isURISafeToResolve(uri, baseURI)) {
+            ResourceResolver resRes = ResourceResolver.getInstance(uri, baseURI, secureValidation);
+            XMLSignatureInput resource = resRes.resolve(uri, baseURI, secureValidation);
+            if (transforms != null) {
+                if (log.isDebugEnabled()) {
+                    log.debug("We have Transforms");
+                    resource = transforms.performTransforms(resource);
+                }
             }
-            resource = transforms.performTransforms(resource);
-        }		
-        return resource;
+            return resource;
+        }
+
+        String uriToResolve = uri != null ? uri.getValue() : null;
+        Object[] exArgs = { uriToResolve != null ? uriToResolve : "null", baseURI };
+
+        throw new ResourceResolverException("utils.resolver.noClass", exArgs, uriToResolve, baseURI);
     }
 
     /**
diff --git a/src/main/java/org/apache/xml/security/resource/xmlsecurity_en.properties b/src/main/java/org/apache/xml/security/resource/xmlsecurity_en.properties
index 4ae18fe..8e8461f 100644
--- a/src/main/java/org/apache/xml/security/resource/xmlsecurity_en.properties
+++ b/src/main/java/org/apache/xml/security/resource/xmlsecurity_en.properties
@@ -124,6 +124,7 @@ signature.Transform.ForbiddenTransform = Transform {0} is forbidden when secure
 signature.Transform.NotYetImplemented = Transform {0} not yet implemented
 signature.Transform.NullPointerTransform = Null pointer as URI. Programming bug?
 signature.Transform.UnknownTransform = Unknown transformation. No handler installed for URI {0}
+signature.Transform.XPathError = Error evaluating XPath expression
 signature.Transform.node = Current Node: {0}
 signature.Transform.nodeAndType = Current Node: {0}, type: {1} 
 signature.Util.BignumNonPositive = bigInteger.signum() must be positive
@@ -193,4 +194,4 @@ stax.signature.keyNameMissing = KeyName not configured.
 stax.keyNotFoundForName = No key configured for KeyName: {0}
 stax.keyTypeNotSupported = Key of type {0} not supported for a KeyName lookup
 stax.idsetbutnotgenerated = An Id attribute is specified, but Id generation is disabled
-stax.idgenerationdisablewithmultipleparts = Id generation must not be disabled when multiple parts need signing
\ No newline at end of file
+stax.idgenerationdisablewithmultipleparts = Id generation must not be disabled when multiple parts need signing
diff --git a/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java b/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java
index f3a099f..9a25bba 100644
--- a/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java
+++ b/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java
@@ -547,7 +547,7 @@ public class XMLSignatureInput {
                 convertToNodes();
             } catch (Exception e) {
                 throw new XMLSecurityRuntimeException(
-                    "signature.XMLSignatureInput.nodesetReference", e
+                    "signature.XMLSignatureInput.nodesetReference"
                 );
             }
         }
diff --git a/src/main/java/org/apache/xml/security/transforms/implementations/TransformXPath.java b/src/main/java/org/apache/xml/security/transforms/implementations/TransformXPath.java
index d5b87d5..aa62028 100644
--- a/src/main/java/org/apache/xml/security/transforms/implementations/TransformXPath.java
+++ b/src/main/java/org/apache/xml/security/transforms/implementations/TransformXPath.java
@@ -144,11 +144,7 @@ public class TransformXPath extends TransformSpi {
                 }
                 return 0;
             } catch (TransformerException e) {
-                Object[] eArgs = {currentNode};
-                throw new XMLSecurityRuntimeException("signature.Transform.node", eArgs, e);
-            } catch (Exception e) {
-                Object[] eArgs = {currentNode, currentNode.getNodeType()};
-                throw new XMLSecurityRuntimeException("signature.Transform.nodeAndType",eArgs, e);
+                throw new XMLSecurityRuntimeException("signature.Transform.XPathError");
             }
         }
 
diff --git a/src/main/java/org/apache/xml/security/utils/resolver/ResourceResolver.java b/src/main/java/org/apache/xml/security/utils/resolver/ResourceResolver.java
index 7e134fe..b969a86 100644
--- a/src/main/java/org/apache/xml/security/utils/resolver/ResourceResolver.java
+++ b/src/main/java/org/apache/xml/security/utils/resolver/ResourceResolver.java
@@ -18,6 +18,8 @@
  */
 package org.apache.xml.security.utils.resolver;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -39,6 +41,11 @@ import org.w3c.dom.Attr;
  */
 public class ResourceResolver {
 
+
+    private static boolean allowUnsafeResourceResolving =
+            AccessController.doPrivileged(
+                    (PrivilegedAction<Boolean>) () -> Boolean.getBoolean("org.apache.xml.security.allowUnsafeResourceResolving"));
+
     private static org.slf4j.Logger log =
         org.slf4j.LoggerFactory.getLogger(ResourceResolver.class);
 
@@ -336,6 +343,23 @@ public class ResourceResolver {
         return resolverSpi.understandsProperty(propertyToTest);
     }
 
+    public static boolean isURISafeToResolve(Attr uriAttr, String baseUri) {
+        if (allowUnsafeResourceResolving) {
+            return true;
+        }
+        String uriToResolve = uriAttr != null ? uriAttr.getValue() : null;
+        if (uriToResolve != null) {
+            if (uriToResolve.startsWith("file:") || uriToResolve.startsWith("http:")) {
+                return false;
+            }
+            if (!uriToResolve.isEmpty() && uriToResolve.charAt(0) != '#' &&
+                    baseUri != null && (baseUri.startsWith("file:") || baseUri.startsWith("http:"))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * Method canResolve
      *
diff --git a/src/test/java/javax/xml/crypto/test/dsig/CreateBaltimore23Test.java b/src/test/java/javax/xml/crypto/test/dsig/CreateBaltimore23Test.java
index accf6a3..08ef412 100644
--- a/src/test/java/javax/xml/crypto/test/dsig/CreateBaltimore23Test.java
+++ b/src/test/java/javax/xml/crypto/test/dsig/CreateBaltimore23Test.java
@@ -79,6 +79,7 @@ public class CreateBaltimore23Test extends org.junit.Assert {
     private final URIDereferencer ud;
 
     static {
+        System.setProperty("org.apache.xml.security.allowUnsafeResourceResolving", "true");
         Security.insertProviderAt
             (new org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI(), 1);
     }
diff --git a/src/test/java/org/apache/xml/security/test/dom/keys/keyresolver/KeyInfoReferenceResolverTest.java b/src/test/java/org/apache/xml/security/test/dom/keys/keyresolver/KeyInfoReferenceResolverTest.java
index eb3fe5d..dbcf65e 100644
--- a/src/test/java/org/apache/xml/security/test/dom/keys/keyresolver/KeyInfoReferenceResolverTest.java
+++ b/src/test/java/org/apache/xml/security/test/dom/keys/keyresolver/KeyInfoReferenceResolverTest.java
@@ -128,6 +128,19 @@ public class KeyInfoReferenceResolverTest extends Assert {
         assertNull(keyInfo.getPublicKey());
     }
 
+    @org.junit.Test
+    public void testKeyInfoReferenceToRetrievalMethodNotAllowed() throws Exception {
+        Document doc = loadXML("KeyInfoReference-RSA-RetrievalMethod.xml");
+        markKeyInfoIdAttrs(doc);
+        markEncodedKeyValueIdAttrs(doc);
+
+        Element referenceElement = doc.getElementById("theReference");
+        assertNotNull(referenceElement);
+
+        KeyInfo keyInfo = new KeyInfo(referenceElement, "");
+        assertNull(keyInfo.getPublicKey());
+    }
+
     // Utility methods
 
     private String getControlFilePath(String fileName) {
@@ -163,4 +176,13 @@ public class KeyInfoReferenceResolverTest extends Assert {
         }
     }
 
+    private void markEncodedKeyValueIdAttrs(Document doc) {
+        NodeList nl = doc.getElementsByTagNameNS(Constants.SignatureSpec11NS, Constants._TAG_DERENCODEDKEYVALUE);
+        for (int i = 0; i < nl.getLength(); i++) {
+            Element keyInfoElement = (Element) nl.item(i);
+            keyInfoElement.setIdAttributeNS(null, Constants._ATT_ID, true);
+        }
+    }
+
 }
+
diff --git a/src/test/resources/org/apache/xml/security/keyresolver/KeyInfoReference-RSA-RetrievalMethod.xml b/src/test/resources/org/apache/xml/security/keyresolver/KeyInfoReference-RSA-RetrievalMethod.xml
new file mode 100644
index 0000000..f34e3d5
--- /dev/null
+++ b/src/test/resources/org/apache/xml/security/keyresolver/KeyInfoReference-RSA-RetrievalMethod.xml
@@ -0,0 +1,22 @@
+<test:root xmlns:test="http://www.example.org/test">
+
+  <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="theRealKey">
+    <dsig11:DEREncodedKeyValue Id="theRealKey2" xmlns:dsig11="http://www.w3.org/2009/xmldsig11#">
+      MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmDnHagSzfia3N7jOaMSp4VIZjK2lxZgN
+      X/2z98YLp1XE3cvpP+mOvX3gENWQuX3uoix+2qroZ0BFHzhzf4E7is5Q9+42ZFi5naFk3c/B0Q8A
+      jtHtWUEZ8VPPBZggz6uJ1ttJS7YDP6XVjaw6SN1bJSD4/lWNIVsh95kuhunbOef6x/kyIbBz9wF4
+      S0//G6zPD4GG7/jJ+sDXe+bAgPB1qwhLhrK3N1jGuDZkGGcY/c4b7aba0B0rognwKlygv16GoA/n
+      zWehxih7clhmMTzP2VWa3Q2GcN8ETe00dz68KtS7GF6W15qftjUvRXEKSoPz86ZsP30jIH1tvIrs
+      qSh/kwIDAQAB
+    </dsig11:DEREncodedKeyValue>
+  </ds:KeyInfo>
+
+  <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="retrievalMethod">
+    <ds:RetrievalMethod URI="#theRealKey2"/>
+  </ds:KeyInfo>
+  
+  <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="theReference">
+    <dsig11:KeyInfoReference xmlns:dsig11="http://www.w3.org/2009/xmldsig11#" URI="#retrievalMethod" />
+  </ds:KeyInfo>
+
+</test:root>