1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.stax.test;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.InputStream;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Properties;
27 import javax.xml.stream.XMLStreamException;
28 import javax.xml.transform.dom.DOMSource;
29 import javax.xml.transform.stream.StreamResult;
30 import javax.xml.xpath.XPathConstants;
31 import javax.xml.xpath.XPathExpression;
32
33 import org.apache.wss4j.common.bsp.BSPRule;
34 import org.apache.wss4j.common.ext.WSSecurityException;
35 import org.apache.wss4j.dom.handler.WSHandlerConstants;
36 import org.apache.wss4j.stax.ext.WSSConstants;
37 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
38 import org.junit.jupiter.api.Test;
39
40 import org.w3c.dom.Attr;
41 import org.w3c.dom.Document;
42 import org.w3c.dom.Element;
43 import org.w3c.dom.NodeList;
44
45 import static org.junit.jupiter.api.Assertions.assertEquals;
46 import static org.junit.jupiter.api.Assertions.assertFalse;
47 import static org.junit.jupiter.api.Assertions.assertNotNull;
48 import static org.junit.jupiter.api.Assertions.assertTrue;
49 import static org.junit.jupiter.api.Assertions.fail;
50
51 public class VulnerabliltyVectorsTest extends AbstractTestBase {
52
53
54
55
56
57
58 @Test
59 public void testRecursiveKeyReferencesDOS() throws Exception {
60 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
61
62 String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
63 Properties properties = new Properties();
64 properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
65 Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
66
67 XPathExpression xPathExpression = getXPath("/soap:Envelope/soap:Header/wsse:Security/xenc:EncryptedKey");
68 Element encryptedKeyElement = (Element) xPathExpression.evaluate(securedDocument, XPathConstants.NODE);
69 encryptedKeyElement.removeAttribute("Id");
70 encryptedKeyElement.setAttributeNS(null, "Id", "G2");
71
72 xPathExpression = getXPath(".//dsig:X509Data");
73 Element keyIdentifierElement = (Element) xPathExpression.evaluate(encryptedKeyElement, XPathConstants.NODE);
74 Element securityTokenReferenceElement = (Element) keyIdentifierElement.getParentNode();
75 securityTokenReferenceElement.removeChild(keyIdentifierElement);
76
77 Element referenceElement = securedDocument.createElementNS(WSSConstants.TAG_WSSE_REFERENCE.getNamespaceURI(), WSSConstants.TAG_WSSE_REFERENCE.getLocalPart());
78 referenceElement.setAttributeNS(null, "URI", "#G1");
79 securityTokenReferenceElement.appendChild(referenceElement);
80
81 Element clonedEncryptedElement = (Element) encryptedKeyElement.cloneNode(true);
82 clonedEncryptedElement.removeAttribute("Id");
83 clonedEncryptedElement.setAttributeNS(null, "Id", "G1");
84
85 xPathExpression = getXPath(".//wsse:Reference");
86 Element newReferenceElement = (Element) xPathExpression.evaluate(clonedEncryptedElement, XPathConstants.NODE);
87 newReferenceElement.removeAttribute("URI");
88 newReferenceElement.setAttributeNS(null, "URI", "#G2");
89
90 Element securityHeaderNode = (Element) encryptedKeyElement.getParentNode();
91 securityHeaderNode.insertBefore(clonedEncryptedElement, encryptedKeyElement);
92
93 ByteArrayOutputStream baos = new ByteArrayOutputStream();
94
95 javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
96 transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
97
98 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
99 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
100 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
101 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
102
103 try {
104 doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
105 fail("Expected XMLStreamException");
106 } catch (XMLStreamException e) {
107 Throwable throwable = e.getCause();
108 assertNotNull(throwable);
109
110
111
112 assertEquals(throwable.getMessage(), "Recursive key reference detected.");
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 @Test
163 public void test_publicURIReferenceDOS() throws Exception {
164 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
165
166 String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
167 Properties properties = new Properties();
168 properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
169 properties.setProperty(WSHandlerConstants.ENC_SYM_ALGO, "http://www.w3.org/2001/04/xmlenc#aes256-cbc");
170 Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
171
172 XPathExpression xPathExpression = getXPath("//@URI");
173 Attr uri = (Attr) xPathExpression.evaluate(securedDocument, XPathConstants.NODE);
174 uri.setNodeValue("http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.gz");
175
176 ByteArrayOutputStream baos = new ByteArrayOutputStream();
177
178 javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
179 transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
180
181 WSSSecurityProperties inSecurityProperties = new WSSSecurityProperties();
182 inSecurityProperties.setCallbackHandler(new CallbackHandlerImpl());
183 inSecurityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
184 inSecurityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
185 inSecurityProperties.addIgnoreBSPRule(BSPRule.R3006);
186
187 try {
188 doInboundSecurity(inSecurityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
189 fail("Expected XMLStreamException");
190 } catch (XMLStreamException e) {
191 Throwable throwable = e.getCause();
192 assertNotNull(throwable);
193 assertTrue(throwable.getMessage().contains("Invalid digest of reference "));
194 }
195 }
196
197 @Test
198 public void testTransformationCodeInjection() throws Exception {
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 @Test
267 public void testMaximumAllowedReferencesPerManifest() throws Exception {
268
269 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
270
271 String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
272 Properties properties = new Properties();
273 properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://www.w3.org/1999/XMLSchema}complexType;{Element}{http://www.w3.org/1999/XMLSchema}simpleType;");
274 Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
275 ByteArrayOutputStream baos = new ByteArrayOutputStream();
276
277 javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
278 transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
279
280 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
281 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
282 securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
283 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
284
285 try {
286 doInboundSecurity(securityProperties,
287 xmlInputFactory.createXMLStreamReader(
288 new ByteArrayInputStream(baos.toByteArray())));
289 fail("Expected XMLStreamException");
290 } catch (XMLStreamException e) {
291 assertTrue(e.getCause() instanceof WSSecurityException);
292 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.INVALID_SECURITY);
293 }
294 }
295
296 @Test
297 public void testDisallowMD5Algorithm() throws Exception {
298 WSSSecurityProperties outboundSecurityProperties = new WSSSecurityProperties();
299 outboundSecurityProperties.setCallbackHandler(new CallbackHandlerImpl());
300 outboundSecurityProperties.setEncryptionUser("receiver");
301 outboundSecurityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
302 outboundSecurityProperties.setSignatureUser("transmitter");
303 outboundSecurityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
304 outboundSecurityProperties.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-md5");
305 List<WSSConstants.Action> actions = new ArrayList<>();
306 actions.add(WSSConstants.TIMESTAMP);
307 actions.add(WSSConstants.SIGNATURE);
308 actions.add(WSSConstants.ENCRYPTION);
309 outboundSecurityProperties.setActions(actions);
310
311 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
312 ByteArrayOutputStream baos = doOutboundSecurity(outboundSecurityProperties, sourceDocument);
313
314 WSSSecurityProperties inboundsecurityProperties = new WSSSecurityProperties();
315 inboundsecurityProperties.setCallbackHandler(new CallbackHandlerImpl());
316 inboundsecurityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
317 inboundsecurityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
318 inboundsecurityProperties.addIgnoreBSPRule(BSPRule.R5421);
319
320 try {
321 doInboundSecurity(inboundsecurityProperties,
322 xmlInputFactory.createXMLStreamReader(
323 new ByteArrayInputStream(baos.toByteArray())));
324 fail("Expected XMLStreamException");
325 } catch (XMLStreamException e) {
326 assertTrue(e.getCause() instanceof WSSecurityException);
327 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.FAILED_CHECK);
328 }
329 }
330
331 @Test
332 public void testModifiedEncryptedKeyCipherValue() throws Exception {
333
334 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
335
336 String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION;
337 Properties properties = new Properties();
338 properties.setProperty(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;");
339 Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
340 ByteArrayOutputStream baos = new ByteArrayOutputStream();
341
342 NodeList cipherValues = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_xenc_CipherValue.getNamespaceURI(), WSSConstants.TAG_xenc_CipherValue.getLocalPart());
343 Element cipherValueElement = (Element)cipherValues.item(0);
344 assertEquals(cipherValueElement.getParentNode().getParentNode().getLocalName(), WSSConstants.TAG_xenc_EncryptedKey.getLocalPart());
345
346 String cipherValue = cipherValueElement.getTextContent();
347 StringBuilder stringBuilder = new StringBuilder(cipherValue);
348 int index = stringBuilder.length() / 2;
349 char ch = stringBuilder.charAt(index);
350 if (ch != 'A') {
351 ch = 'A';
352 } else {
353 ch = 'B';
354 }
355 stringBuilder.setCharAt(index, ch);
356 cipherValueElement.setTextContent(stringBuilder.toString());
357
358 javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
359 transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
360
361 WSSSecurityProperties inboundsecurityProperties = new WSSSecurityProperties();
362 inboundsecurityProperties.setCallbackHandler(new CallbackHandlerImpl());
363 inboundsecurityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
364 inboundsecurityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
365
366 try {
367 doInboundSecurity(inboundsecurityProperties,
368 xmlInputFactory.createXMLStreamReader(
369 new ByteArrayInputStream(baos.toByteArray())));
370 fail("Expected XMLStreamException");
371 } catch (XMLStreamException e) {
372 assertFalse(e.getMessage().contains("data hash wrong"));
373 }
374 }
375
376
377
378
379
380 @Test
381 public void testDisallowRSA15Algorithm() throws Exception {
382 WSSSecurityProperties outboundSecurityProperties = new WSSSecurityProperties();
383 outboundSecurityProperties.setCallbackHandler(new CallbackHandlerImpl());
384 outboundSecurityProperties.setEncryptionUser("receiver");
385 outboundSecurityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
386 outboundSecurityProperties.setSignatureUser("transmitter");
387 outboundSecurityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
388 outboundSecurityProperties.setEncryptionKeyTransportAlgorithm("http://www.w3.org/2001/04/xmlenc#rsa-1_5");
389 List<WSSConstants.Action> actions = new ArrayList<>();
390 actions.add(WSSConstants.TIMESTAMP);
391 actions.add(WSSConstants.SIGNATURE);
392 actions.add(WSSConstants.ENCRYPTION);
393 outboundSecurityProperties.setActions(actions);
394
395 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
396 ByteArrayOutputStream baos = doOutboundSecurity(outboundSecurityProperties, sourceDocument);
397
398 WSSSecurityProperties inboundsecurityProperties = new WSSSecurityProperties();
399 inboundsecurityProperties.setCallbackHandler(new CallbackHandlerImpl());
400 inboundsecurityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
401 inboundsecurityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
402 inboundsecurityProperties.addIgnoreBSPRule(BSPRule.R5421);
403
404 try {
405 doInboundSecurity(inboundsecurityProperties,
406 xmlInputFactory.createXMLStreamReader(
407 new ByteArrayInputStream(baos.toByteArray())));
408 fail("Expected XMLStreamException");
409 } catch (XMLStreamException e) {
410 assertTrue(e.getCause() instanceof WSSecurityException);
411 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.FAILED_CHECK);
412 }
413 }
414 }