You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2018/05/17 16:31:03 UTC

[cxf-fediz] branch master updated (a0f5a45 -> 09dbe37)

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/cxf-fediz.git.


    from a0f5a45  Updating Tomcat
     new beb87ff  Adding a modified SignatureValue test for SAML SSO
     new b59bb8b  Add support to redirect the SAML SSO RP when the session expires
     new e24d0e5  Adding entity expansion attacks for SAML SSO
     new 09dbe37  Adding CSRF tests for SAML SSO

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../fediz/core/processor/SAMLProcessorImpl.java    |  10 +-
 .../core/samlsso/SAMLSSOResponseValidator.java     |   4 +-
 .../fediz/systests/samlsso/Tomcat8PluginTest.java  | 133 +++++++++++++++++++++
 systests/tests/pom.xml                             |   5 +
 .../cxf/fediz/systests/common/AbstractTests.java   | 132 ++++++++++++++------
 .../cxf/fediz/systests/tomcat8/TomcatTest.java     |  62 ++++++++++
 6 files changed, 298 insertions(+), 48 deletions(-)

-- 
To stop receiving notification emails like this one, please contact
coheigea@apache.org.

[cxf-fediz] 04/04: Adding CSRF tests for SAML SSO

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf-fediz.git

commit 09dbe375600623aafa5e92838d74f3409d1bf2dd
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Thu May 17 17:30:42 2018 +0100

    Adding CSRF tests for SAML SSO
---
 .../cxf/fediz/systests/common/AbstractTests.java   | 45 +++++++++++++---------
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java b/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
index df17bdc..ebdfea7 100644
--- a/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
+++ b/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
@@ -888,10 +888,6 @@ public abstract class AbstractTests {
     @org.junit.Test
     public void testCSRFAttack() throws Exception {
 
-        if (!isWSFederation()) {
-            return;
-        }
-
         String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
         csrfAttackTest(url);
     }
@@ -913,7 +909,7 @@ public abstract class AbstractTests {
         webClient.getOptions().setJavaScriptEnabled(true);
         Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
 
-        final HtmlForm form = idpPage.getFormByName("signinresponseform");
+        final HtmlForm form = idpPage.getFormByName(getLoginFormName());
         final HtmlSubmitInput button = form.getInputByName("_eventId_submit");
 
         final HtmlPage rpPage = button.click();
@@ -942,11 +938,19 @@ public abstract class AbstractTests {
         DomNodeList<DomElement> results = idpPage2.getElementsByTagName("input");
 
         for (DomElement result : results) {
-            if ("wresult".equals(result.getAttributeNS(null, "name"))
-                || "wa".equals(result.getAttributeNS(null, "name"))
-                || "wctx".equals(result.getAttributeNS(null, "name"))) {
-                String value = result.getAttributeNS(null, "value");
-                request.getRequestParameters().add(new NameValuePair(result.getAttributeNS(null, "name"), value));
+            if (isWSFederation()) {
+                if ("wresult".equals(result.getAttributeNS(null, "name"))
+                    || "wa".equals(result.getAttributeNS(null, "name"))
+                    || "wctx".equals(result.getAttributeNS(null, "name"))) {
+                    String value = result.getAttributeNS(null, "value");
+                    request.getRequestParameters().add(new NameValuePair(result.getAttributeNS(null, "name"), value));
+                }
+            } else {
+                if ("SAMLResponse".equals(result.getAttributeNS(null, "name"))
+                    || "RelayState".equals(result.getAttributeNS(null, "name"))) {
+                    String value = result.getAttributeNS(null, "value");
+                    request.getRequestParameters().add(new NameValuePair(result.getAttributeNS(null, "name"), value));
+                }
             }
         }
 
@@ -964,9 +968,6 @@ public abstract class AbstractTests {
 
     @org.junit.Test
     public void testCSRFAttack2() throws Exception {
-        if (!isWSFederation()) {
-            return;
-        }
 
         String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
         csrfAttackTest2(url);
@@ -996,11 +997,19 @@ public abstract class AbstractTests {
         DomNodeList<DomElement> results = idpPage2.getElementsByTagName("input");
 
         for (DomElement result : results) {
-            if ("wresult".equals(result.getAttributeNS(null, "name"))
-                || "wa".equals(result.getAttributeNS(null, "name"))
-                || "wctx".equals(result.getAttributeNS(null, "name"))) {
-                String value = result.getAttributeNS(null, "value");
-                request.getRequestParameters().add(new NameValuePair(result.getAttributeNS(null, "name"), value));
+            if (isWSFederation()) {
+                if ("wresult".equals(result.getAttributeNS(null, "name"))
+                    || "wa".equals(result.getAttributeNS(null, "name"))
+                    || "wctx".equals(result.getAttributeNS(null, "name"))) {
+                    String value = result.getAttributeNS(null, "value");
+                    request.getRequestParameters().add(new NameValuePair(result.getAttributeNS(null, "name"), value));
+                }
+            } else {
+                if ("SAMLResponse".equals(result.getAttributeNS(null, "name"))
+                    || "RelayState".equals(result.getAttributeNS(null, "name"))) {
+                    String value = result.getAttributeNS(null, "value");
+                    request.getRequestParameters().add(new NameValuePair(result.getAttributeNS(null, "name"), value));
+                }
             }
         }
 

-- 
To stop receiving notification emails like this one, please contact
coheigea@apache.org.

[cxf-fediz] 01/04: Adding a modified SignatureValue test for SAML SSO

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf-fediz.git

commit beb87ff1df447dcd4314f5f47ecc03d6b132eae4
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Thu May 17 14:23:33 2018 +0100

    Adding a modified SignatureValue test for SAML SSO
---
 .../fediz/systests/samlsso/Tomcat8PluginTest.java  | 83 ++++++++++++++++++++++
 .../cxf/fediz/systests/common/AbstractTests.java   |  4 +-
 2 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java
index ab9c4e1..73a774f 100644
--- a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java
+++ b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java
@@ -19,10 +19,13 @@
 
 package org.apache.cxf.fediz.systests.samlsso;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 
 import javax.servlet.ServletException;
 
@@ -32,11 +35,28 @@ import org.apache.catalina.LifecycleState;
 import org.apache.catalina.connector.Connector;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.commons.io.IOUtils;
+import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.fediz.systests.common.AbstractTests;
 import org.apache.cxf.fediz.tomcat8.FederationAuthenticator;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.wss4j.common.util.DOM2Writer;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import com.gargoylesoftware.htmlunit.CookieManager;
+import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.DomElement;
+import com.gargoylesoftware.htmlunit.html.DomNodeList;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
 
 /**
  * Some tests for SAML SSO with the Tomcat 8 plugin, invoking on the Fediz IdP configured for SAML SSO.
@@ -177,4 +197,67 @@ public class Tomcat8PluginTest extends AbstractTests {
         Thread.sleep(5 * 60 * 1000);
     }
 
+    @Test
+    public void testModifiedSignatureValue() throws Exception {
+
+        String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName()
+            + "/secure/fedservlet";
+        String user = "alice";
+        String password = "ecila";
+
+        // Get the initial token
+        CookieManager cookieManager = new CookieManager();
+        final WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        final HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+
+        // Parse the form to get the token (wresult)
+        DomNodeList<DomElement> results = idpPage.getElementsByTagName("input");
+
+        for (DomElement result : results) {
+            if (getTokenNameFromForm().equals(result.getAttributeNS(null, "name"))) {
+                String value = result.getAttributeNS(null, "value");
+
+                // Decode response
+                byte[] deflatedToken = Base64Utility.decode(value);
+                InputStream inputStream = new ByteArrayInputStream(deflatedToken);
+
+                Document responseDoc = StaxUtils.read(new InputStreamReader(inputStream, "UTF-8"));
+
+                // Modify SignatureValue
+                String signatureNamespace = "http://www.w3.org/2000/09/xmldsig#";
+                Node signatureValue =
+                    responseDoc.getElementsByTagNameNS(signatureNamespace, "SignatureValue").item(0);
+                signatureValue.setTextContent("H" + signatureValue.getTextContent());
+
+                // Re-encode response
+                String responseMessage = DOM2Writer.nodeToString(responseDoc);
+                result.setAttributeNS(null, "value", Base64Utility.encode(responseMessage.getBytes()));
+            }
+        }
+
+        // Invoke back on the RP
+
+        final HtmlForm form = idpPage.getFormByName(getLoginFormName());
+        final HtmlSubmitInput button = form.getInputByName("_eventId_submit");
+
+        try {
+            button.click();
+            Assert.fail("Failure expected on a modified signature");
+        } catch (FailingHttpStatusCodeException ex) {
+            // expected
+            Assert.assertTrue(401 == ex.getStatusCode() || 403 == ex.getStatusCode());
+        }
+
+        webClient.close();
+    }
+
 }
diff --git a/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java b/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
index 32e1499..ec7bf24 100644
--- a/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
+++ b/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
@@ -72,14 +72,14 @@ public abstract class AbstractTests {
         return true;
     }
 
-    private String getLoginFormName() {
+    protected String getLoginFormName() {
         if (isWSFederation()) {
             return "signinresponseform";
         }
         return "samlsigninresponseform";
     }
 
-    private String getTokenNameFromForm() {
+    protected String getTokenNameFromForm() {
         if (isWSFederation()) {
             return "wresult";
         }

-- 
To stop receiving notification emails like this one, please contact
coheigea@apache.org.

[cxf-fediz] 02/04: Add support to redirect the SAML SSO RP when the session expires

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf-fediz.git

commit b59bb8b15d5c39314687c8cd693c6731eb7537ab
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Thu May 17 17:09:12 2018 +0100

    Add support to redirect the SAML SSO RP when the session expires
---
 .../fediz/core/processor/SAMLProcessorImpl.java    | 10 ++--
 .../core/samlsso/SAMLSSOResponseValidator.java     |  4 +-
 .../fediz/systests/samlsso/Tomcat8PluginTest.java  | 52 +++++++++++++++++-
 .../cxf/fediz/systests/common/AbstractTests.java   | 14 +++--
 .../cxf/fediz/systests/tomcat8/TomcatTest.java     | 62 ++++++++++++++++++++++
 5 files changed, 129 insertions(+), 13 deletions(-)

diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java
index 4fd1be8..cbffb5e 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java
@@ -111,10 +111,6 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor {
             LOG.error("Invalid RelayState");
             throw new ProcessingException(TYPE.INVALID_REQUEST);
         }
-        if (requestState == null) {
-            LOG.error("Missing Request State");
-            throw new ProcessingException(TYPE.INVALID_REQUEST);
-        }
         return requestState;
     }
 
@@ -262,9 +258,9 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor {
                 ((SAMLProtocol)config.getProtocol()).isDoNotEnforceKnownIssuer();
             ssoResponseValidator.setEnforceKnownIssuer(!doNotEnforceKnownIssuer);
 
-            ssoResponseValidator.setIssuerIDP(requestState.getIdpServiceAddress());
-            ssoResponseValidator.setRequestId(requestState.getRequestId());
-            ssoResponseValidator.setSpIdentifier(requestState.getIssuerId());
+            ssoResponseValidator.setIssuerIDP(requestState != null ? requestState.getIdpServiceAddress() : null);
+            ssoResponseValidator.setRequestId(requestState != null ? requestState.getRequestId() : null);
+            ssoResponseValidator.setSpIdentifier(requestState != null ? requestState.getIssuerId() : null);
             ssoResponseValidator.setEnforceAssertionsSigned(true);
             ssoResponseValidator.setReplayCache(config.getTokenReplayCache());
 
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java
index c92da54..06bb70f 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java
@@ -161,7 +161,7 @@ public class SAMLSSOResponseValidator {
         }
 
         // Issuer value must match (be contained in) Issuer IDP
-        if (enforceKnownIssuer && !issuerIDP.startsWith(issuer.getValue())) {
+        if (enforceKnownIssuer && issuerIDP != null && !issuerIDP.startsWith(issuer.getValue())) {
             LOG.debug("Issuer value: " + issuer.getValue() + " does not match issuer IDP: "
                 + issuerIDP);
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
@@ -269,7 +269,7 @@ public class SAMLSSOResponseValidator {
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
         }
         List<AudienceRestriction> audienceRestrs = conditions.getAudienceRestrictions();
-        if (!matchSaml2AudienceRestriction(spIdentifier, audienceRestrs)) {
+        if (spIdentifier != null && !matchSaml2AudienceRestriction(spIdentifier, audienceRestrs)) {
             LOG.debug("Assertion does not contain unique subject provider identifier "
                      + spIdentifier + " in the audience restriction conditions");
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
diff --git a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java
index 73a774f..82a488a 100644
--- a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java
+++ b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java
@@ -223,7 +223,7 @@ public class Tomcat8PluginTest extends AbstractTests {
         DomNodeList<DomElement> results = idpPage.getElementsByTagName("input");
 
         for (DomElement result : results) {
-            if (getTokenNameFromForm().equals(result.getAttributeNS(null, "name"))) {
+            if (getTokenName().equals(result.getAttributeNS(null, "name"))) {
                 String value = result.getAttributeNS(null, "value");
 
                 // Decode response
@@ -259,5 +259,55 @@ public class Tomcat8PluginTest extends AbstractTests {
 
         webClient.close();
     }
+    
+    @Test
+    public void testAliceModifiedContext() throws Exception {
+
+        String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName()
+            + "/secure/fedservlet";
+        String user = "alice";
+        String password = "ecila";
+
+        // Get the initial token
+        CookieManager cookieManager = new CookieManager();
+        final WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        final HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+
+        // Parse the form to get the token (wresult)
+        DomNodeList<DomElement> results = idpPage.getElementsByTagName("input");
+
+        for (DomElement result : results) {
+            if (getContextName().equals(result.getAttributeNS(null, "name"))) {
+                // Now modify the context
+                String value = result.getAttributeNS(null, "value");
+                value = "H" + value;
+                result.setAttributeNS(null, "value", value);
+            }
+        }
+
+        // Invoke back on the RP
+
+        final HtmlForm form = idpPage.getFormByName(getLoginFormName());
+        final HtmlSubmitInput button = form.getInputByName("_eventId_submit");
+
+        try {
+            button.click();
+            Assert.fail("Failure expected on a modified context");
+        } catch (FailingHttpStatusCodeException ex) {
+            // Request Timeout expected here, as the context isn't known - the session is presumed to have expired
+            Assert.assertTrue(408 == ex.getStatusCode());
+        }
+
+        webClient.close();
+    }
 
 }
diff --git a/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java b/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
index ec7bf24..da6dfdf 100644
--- a/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
+++ b/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
@@ -79,7 +79,7 @@ public abstract class AbstractTests {
         return "samlsigninresponseform";
     }
 
-    protected String getTokenNameFromForm() {
+    protected String getTokenName() {
         if (isWSFederation()) {
             return "wresult";
         }
@@ -87,6 +87,14 @@ public abstract class AbstractTests {
         return "SAMLResponse";
     }
 
+    protected String getContextName() {
+        if (isWSFederation()) {
+            return "wctx";
+        }
+
+        return "RelayState";
+    }
+
     @Test
     public void testAlice() throws Exception {
         String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName()
@@ -600,13 +608,13 @@ public abstract class AbstractTests {
         DomNodeList<DomElement> results = idpPage.getElementsByTagName("input");
 
         for (DomElement result : results) {
-            if (getTokenNameFromForm().equals(result.getAttributeNS(null, "name"))) {
+            if (getTokenName().equals(result.getAttributeNS(null, "name"))) {
                 // Now modify the Signature
                 String value = result.getAttributeNS(null, "value");
                 if (value.contains("alice")) {
                     value = value.replace("alice", "bob");
                 } else {
-                    value += "H";
+                    value = "H" + value;
                 }
                 result.setAttributeNS(null, "value", value);
             }
diff --git a/systests/tomcat8/src/test/java/org/apache/cxf/fediz/systests/tomcat8/TomcatTest.java b/systests/tomcat8/src/test/java/org/apache/cxf/fediz/systests/tomcat8/TomcatTest.java
index ffff69c..194f060 100644
--- a/systests/tomcat8/src/test/java/org/apache/cxf/fediz/systests/tomcat8/TomcatTest.java
+++ b/systests/tomcat8/src/test/java/org/apache/cxf/fediz/systests/tomcat8/TomcatTest.java
@@ -35,9 +35,21 @@ import org.apache.catalina.startup.Tomcat;
 import org.apache.commons.io.IOUtils;
 import org.apache.cxf.fediz.systests.common.AbstractTests;
 import org.apache.cxf.fediz.tomcat8.FederationAuthenticator;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.gargoylesoftware.htmlunit.CookieManager;
+import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.DomElement;
+import com.gargoylesoftware.htmlunit.html.DomNodeList;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
 
 public class TomcatTest extends AbstractTests {
 
@@ -160,5 +172,55 @@ public class TomcatTest extends AbstractTests {
     public String getServletContextName() {
         return "fedizhelloworld";
     }
+    
+    @Test
+    public void testAliceModifiedContext() throws Exception {
+
+        String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName()
+            + "/secure/fedservlet";
+        String user = "alice";
+        String password = "ecila";
+
+        // Get the initial token
+        CookieManager cookieManager = new CookieManager();
+        final WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        final HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+
+        // Parse the form to get the token (wresult)
+        DomNodeList<DomElement> results = idpPage.getElementsByTagName("input");
+
+        for (DomElement result : results) {
+            if (getContextName().equals(result.getAttributeNS(null, "name"))) {
+                // Now modify the context
+                String value = result.getAttributeNS(null, "value");
+                value = "H" + value;
+                result.setAttributeNS(null, "value", value);
+            }
+        }
+
+        // Invoke back on the RP
+
+        final HtmlForm form = idpPage.getFormByName(getLoginFormName());
+        final HtmlSubmitInput button = form.getInputByName("_eventId_submit");
+
+        try {
+            button.click();
+            Assert.fail("Failure expected on a modified context");
+        } catch (FailingHttpStatusCodeException ex) {
+            // Request Timeout expected here, as the context isn't known - the session is presumed to have expired
+            Assert.assertTrue(408 == ex.getStatusCode());
+        }
+
+        webClient.close();
+    }
 
 }

-- 
To stop receiving notification emails like this one, please contact
coheigea@apache.org.

[cxf-fediz] 03/04: Adding entity expansion attacks for SAML SSO

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf-fediz.git

commit e24d0e57844c1123acfe75c8926788e28ae78b47
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Thu May 17 17:22:35 2018 +0100

    Adding entity expansion attacks for SAML SSO
---
 systests/tests/pom.xml                             |  5 ++
 .../cxf/fediz/systests/common/AbstractTests.java   | 71 ++++++++++++++++------
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/systests/tests/pom.xml b/systests/tests/pom.xml
index 03e813c..a5750fa 100644
--- a/systests/tests/pom.xml
+++ b/systests/tests/pom.xml
@@ -45,6 +45,11 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-core</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+        <dependency>
             <groupId>net.sourceforge.htmlunit</groupId>
             <artifactId>htmlunit</artifactId>
             <version>${htmlunit.version}</version>
diff --git a/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java b/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
index da6dfdf..df17bdc 100644
--- a/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
+++ b/systests/tests/src/test/java/org/apache/cxf/fediz/systests/common/AbstractTests.java
@@ -19,6 +19,9 @@
 
 package org.apache.cxf.fediz.systests.common;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.util.ArrayList;
@@ -41,11 +44,14 @@ import com.gargoylesoftware.htmlunit.util.NameValuePair;
 import com.gargoylesoftware.htmlunit.xml.XmlPage;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.fediz.core.ClaimTypes;
 import org.apache.cxf.fediz.core.FederationConstants;
 import org.apache.cxf.fediz.core.util.DOMUtils;
+import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.wss4j.common.util.DOM2Writer;
 import org.apache.wss4j.dom.engine.WSSConfig;
 import org.apache.xml.security.keys.KeyInfo;
 import org.apache.xml.security.signature.XMLSignature;
@@ -736,10 +742,6 @@ public abstract class AbstractTests {
     @Test
     public void testEntityExpansionAttack() throws Exception {
 
-        if (!isWSFederation()) {
-            return;
-        }
-
         String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
         String user = "alice";
         String password = "ecila";
@@ -766,18 +768,37 @@ public abstract class AbstractTests {
         String reference = "&m;";
 
         for (DomElement result : results) {
-            if ("wresult".equals(result.getAttributeNS(null, "name"))) {
+            if (getTokenName().equals(result.getAttributeNS(null, "name"))) {
                 // Now modify the Signature
                 String value = result.getAttributeNS(null, "value");
-                value = entity + value;
-                value = value.replace("alice", reference);
-                result.setAttributeNS(null, "value", value);
+                
+                if (isWSFederation()) {
+                    value = entity + value;
+                    value = value.replace("alice", reference);
+                    result.setAttributeNS(null, "value", value);
+                } else {
+                    // Decode response
+                    byte[] deflatedToken = Base64Utility.decode(value);
+                    InputStream inputStream = new ByteArrayInputStream(deflatedToken);
+
+                    Document responseDoc = StaxUtils.read(new InputStreamReader(inputStream, "UTF-8"));
+                    
+                    // Modify SignatureValue to include the entity
+                    String signatureNamespace = "http://www.w3.org/2000/09/xmldsig#";
+                    Node signatureValue =
+                        responseDoc.getElementsByTagNameNS(signatureNamespace, "SignatureValue").item(0);
+                    signatureValue.setTextContent(reference + signatureValue.getTextContent());
+                    
+                    // Re-encode response
+                    String responseMessage = DOM2Writer.nodeToString(responseDoc);
+                    result.setAttributeNS(null, "value", Base64Utility.encode((entity + responseMessage).getBytes()));
+                }
             }
         }
 
         // Invoke back on the RP
 
-        final HtmlForm form = idpPage.getFormByName("signinresponseform");
+        final HtmlForm form = idpPage.getFormByName(getLoginFormName());
         final HtmlSubmitInput button = form.getInputByName("_eventId_submit");
 
         try {
@@ -793,9 +814,6 @@ public abstract class AbstractTests {
 
     @Test
     public void testEntityExpansionAttack2() throws Exception {
-        if (!isWSFederation()) {
-            return;
-        }
 
         String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
         String user = "alice";
@@ -823,18 +841,37 @@ public abstract class AbstractTests {
         String reference = "&m;";
 
         for (DomElement result : results) {
-            if ("wresult".equals(result.getAttributeNS(null, "name"))) {
+            if (getTokenName().equals(result.getAttributeNS(null, "name"))) {
                 // Now modify the Signature
                 String value = result.getAttributeNS(null, "value");
-                value = entity + value;
-                value = value.replace("alice", reference);
-                result.setAttributeNS(null, "value", value);
+                
+                if (isWSFederation()) {
+                    value = entity + value;
+                    value = value.replace("alice", reference);
+                    result.setAttributeNS(null, "value", value);
+                } else {
+                    // Decode response
+                    byte[] deflatedToken = Base64Utility.decode(value);
+                    InputStream inputStream = new ByteArrayInputStream(deflatedToken);
+
+                    Document responseDoc = StaxUtils.read(new InputStreamReader(inputStream, "UTF-8"));
+                    
+                    // Modify SignatureValue to include the entity
+                    String signatureNamespace = "http://www.w3.org/2000/09/xmldsig#";
+                    Node signatureValue =
+                        responseDoc.getElementsByTagNameNS(signatureNamespace, "SignatureValue").item(0);
+                    signatureValue.setTextContent(reference + signatureValue.getTextContent());
+                    
+                    // Re-encode response
+                    String responseMessage = DOM2Writer.nodeToString(responseDoc);
+                    result.setAttributeNS(null, "value", Base64Utility.encode((entity + responseMessage).getBytes()));
+                }
             }
         }
 
         // Invoke back on the RP
 
-        final HtmlForm form = idpPage.getFormByName("signinresponseform");
+        final HtmlForm form = idpPage.getFormByName(getLoginFormName());
         final HtmlSubmitInput button = form.getInputByName("_eventId_submit");
 
         try {

-- 
To stop receiving notification emails like this one, please contact
coheigea@apache.org.