This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch 3_0_x-fixes
in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
The following commit(s) were added to refs/heads/3_0_x-fixes by this push:
new fae5e611f EncryptedHeader child confusion causing wrong
protected-header selection (#687)
fae5e611f is described below
commit fae5e611f626b5fec3a729eed50ac00d2d3bc24b
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Fri Sep 11 11:31:12 2026 +0100
EncryptedHeader child confusion causing wrong protected-header selection
(#687)
---
.../org/apache/wss4j/dom/util/EncryptionUtils.java | 23 ++++++++++-
.../apache/wss4j/dom/message/EncryptionTest.java | 48 ++++++++++++++++++++++
2 files changed, 70 insertions(+), 1 deletion(-)
diff --git
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
index f01f07a1b..9240f725f 100644
---
a/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
+++
b/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/EncryptionUtils.java
@@ -90,6 +90,12 @@ public final class EncryptionUtils {
while (child != null && child.getNodeType() != Node.ELEMENT_NODE) {
child = child.getNextSibling();
}
+ if (child == null || !"EncryptedData".equals(child.getLocalName())
+ || !WSConstants.ENC_NS.equals(child.getNamespaceURI())) {
+ throw new WSSecurityException(
+ WSSecurityException.ErrorCode.INVALID_SECURITY, "dataRef",
+ new Object[] {dataRefURI});
+ }
return (Element)child;
}
return encryptedDataElement;
@@ -218,7 +224,22 @@ public final class EncryptionUtils {
|| parent.getLocalName().equals(WSConstants.ENCRYPED_ASSERTION_LN)
&& parent.getNamespaceURI().equals(WSConstants.SAML2_NS)) {
- Node decryptedHeader = parent.getFirstChild();
+ // The decrypted node sits where the EncryptedData was, which is
not necessarily
+ // the wrapper's first child - anything else there was never
encrypted.
+ Node decryptedHeader = decryptedNode;
+ if (decryptedHeader == null) {
+ if (content) {
+ decryptedHeader = encData;
+ } else if (previousSibling == null) {
+ decryptedHeader = parent.getFirstChild();
+ } else {
+ decryptedHeader = previousSibling.getNextSibling();
+ }
+ }
+ if (decryptedHeader == null || Node.ELEMENT_NODE !=
decryptedHeader.getNodeType()) {
+ throw new
WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
+ }
+
Node soapHeader = parent.getParentNode();
soapHeader.replaceChild(decryptedHeader, parent);
diff --git
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java
index 6e44a441b..1bbaa6fd0 100644
---
a/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java
+++
b/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java
@@ -62,6 +62,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.w3c.dom.Node;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -92,6 +93,53 @@ public class EncryptionTest {
crypto = CryptoFactory.getInstance("wss40.properties");
}
+ @Test
+ public void testEncryptedHeaderWithUnencryptedFirstChild() throws
Exception {
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecHeader secHeader = new WSSecHeader(doc);
+ secHeader.insertSecurityHeader();
+ Element soapHeader = (Element)doc.getElementsByTagNameNS(
+ WSConstants.URI_SOAP11_ENV, "Header").item(0);
+ Element header = doc.createElementNS("urn:test", "test:header");
+ header.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:test", "urn:test");
+ soapHeader.appendChild(header);
+
+ WSSecEncrypt builder = new WSSecEncrypt(secHeader);
+ builder.setUserInfo("wss40");
+ builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+ builder.getParts().add(new WSEncryptionPart("header", "urn:test",
"Header"));
+
+ Document encryptedDoc = builder.build(crypto, key);
+ Element encryptedHeader = (Element)encryptedDoc.getElementsByTagNameNS(
+ WSConstants.WSSE11_NS, WSConstants.ENCRYPTED_HEADER).item(0);
+ Node encryptedData = encryptedHeader.getFirstChild();
+ while (encryptedData != null && encryptedData.getNodeType() !=
Node.ELEMENT_NODE) {
+ encryptedData = encryptedData.getNextSibling();
+ }
+ Element unencryptedHeader = encryptedDoc.createElementNS(
+ "urn:attacker", "attacker:header");
+ unencryptedHeader.setAttributeNS(
+ WSConstants.XMLNS_NS, "xmlns:attacker", "urn:attacker");
+ encryptedHeader.insertBefore(unencryptedHeader, encryptedData);
+
+ WSHandlerResult results = secEngine.processSecurityHeader(
+ encryptedDoc, null, keystoreCallbackHandler, crypto);
+
+ Element promotedHeader = (Element)encryptedDoc.getElementsByTagNameNS(
+ "urn:test", "header").item(0);
+ assertNotNull(promotedHeader);
+ assertEquals("urn:test", promotedHeader.getNamespaceURI());
+ assertEquals("header", promotedHeader.getLocalName());
+ assertEquals(0, encryptedDoc.getElementsByTagNameNS(
+ "urn:attacker", "header").getLength());
+
+ @SuppressWarnings("unchecked")
+ java.util.List<WSDataRef> dataRefs =
(java.util.List<WSDataRef>)results.getActionResults()
+
.get(WSConstants.ENCR).get(0).get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
+ assertEquals(1, dataRefs.size());
+ assertEquals(promotedHeader, dataRefs.get(0).getProtectedElement());
+ }
+
/**
* Setup method
*