Repository: cxf-fediz Updated Branches: refs/heads/master 6310703bb -> a5f80c992
Adding a test Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/a5f80c99 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/a5f80c99 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/a5f80c99 Branch: refs/heads/master Commit: a5f80c992169eada88069e3ab2f6154b4f01f3b7 Parents: 6310703 Author: Colm O hEigeartaigh <[email protected]> Authored: Fri Jul 3 15:43:41 2015 +0100 Committer: Colm O hEigeartaigh <[email protected]> Committed: Fri Jul 3 15:43:41 2015 +0100 ---------------------------------------------------------------------- .../EntityExpansionAttackTest.java | 247 +++++++++++++++++++ systests/tomcat7/src/test/resources/entity.xml | 25 ++ 2 files changed, 272 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/a5f80c99/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/EntityExpansionAttackTest.java ---------------------------------------------------------------------- diff --git a/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/EntityExpansionAttackTest.java b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/EntityExpansionAttackTest.java new file mode 100644 index 0000000..006fa2a --- /dev/null +++ b/systests/tomcat7/src/test/java/org/apache/cxf/fediz/integrationtests/EntityExpansionAttackTest.java @@ -0,0 +1,247 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.fediz.integrationtests; + + +import java.io.File; +import java.io.FileInputStream; + +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; + +import org.apache.catalina.Context; +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.fediz.tomcat.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; + +public class EntityExpansionAttackTest { + + static String idpHttpsPort; + static String rpHttpsPort; + + private static Tomcat idpServer; + private static Tomcat rpServer; + + @BeforeClass + public static void init() { + System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog"); + System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true"); + System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "info"); + System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "info"); + System.setProperty("org.apache.commons.logging.simplelog.log.org.springframework.webflow", "info"); + System.setProperty("org.apache.commons.logging.simplelog.log.org.springframework.security.web", "info"); + System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.cxf.fediz", "info"); + System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.cxf", "info"); + + idpHttpsPort = System.getProperty("idp.https.port"); + Assert.assertNotNull("Property 'idp.https.port' null", idpHttpsPort); + rpHttpsPort = System.getProperty("rp.https.port"); + Assert.assertNotNull("Property 'rp.https.port' null", rpHttpsPort); + + initIdp(); + initRp(); + } + + private static void initIdp() { + try { + idpServer = new Tomcat(); + idpServer.setPort(0); + String currentDir = new File(".").getCanonicalPath(); + idpServer.setBaseDir(currentDir + File.separator + "target"); + + idpServer.getHost().setAppBase("tomcat/idp/webapps"); + idpServer.getHost().setAutoDeploy(true); + idpServer.getHost().setDeployOnStartup(true); + + Connector httpsConnector = new Connector(); + httpsConnector.setPort(Integer.parseInt(idpHttpsPort)); + httpsConnector.setSecure(true); + httpsConnector.setScheme("https"); + //httpsConnector.setAttribute("keyAlias", keyAlias); + httpsConnector.setAttribute("keystorePass", "tompass"); + httpsConnector.setAttribute("keystoreFile", "test-classes/server.jks"); + httpsConnector.setAttribute("truststorePass", "tompass"); + httpsConnector.setAttribute("truststoreFile", "test-classes/server.jks"); + httpsConnector.setAttribute("clientAuth", "want"); + // httpsConnector.setAttribute("clientAuth", "false"); + httpsConnector.setAttribute("sslProtocol", "TLS"); + httpsConnector.setAttribute("SSLEnabled", true); + + idpServer.getService().addConnector(httpsConnector); + + idpServer.addWebapp("/fediz-idp-sts", "fediz-idp-sts"); + idpServer.addWebapp("/fediz-idp", "fediz-idp"); + + idpServer.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void initRp() { + try { + rpServer = new Tomcat(); + rpServer.setPort(0); + String currentDir = new File(".").getCanonicalPath(); + rpServer.setBaseDir(currentDir + File.separator + "target"); + + rpServer.getHost().setAppBase("tomcat/rp/webapps"); + rpServer.getHost().setAutoDeploy(true); + rpServer.getHost().setDeployOnStartup(true); + + Connector httpsConnector = new Connector(); + httpsConnector.setPort(Integer.parseInt(rpHttpsPort)); + httpsConnector.setSecure(true); + httpsConnector.setScheme("https"); + //httpsConnector.setAttribute("keyAlias", keyAlias); + httpsConnector.setAttribute("keystorePass", "tompass"); + httpsConnector.setAttribute("keystoreFile", "test-classes/server.jks"); + httpsConnector.setAttribute("truststorePass", "tompass"); + httpsConnector.setAttribute("truststoreFile", "test-classes/server.jks"); + // httpsConnector.setAttribute("clientAuth", "false"); + httpsConnector.setAttribute("clientAuth", "want"); + httpsConnector.setAttribute("sslProtocol", "TLS"); + httpsConnector.setAttribute("SSLEnabled", true); + + rpServer.getService().addConnector(httpsConnector); + + //Context ctx = + Context cxt = rpServer.addWebapp("/fedizhelloworld", "simpleWebapp"); + FederationAuthenticator fa = new FederationAuthenticator(); + fa.setConfigFile(currentDir + File.separator + "target" + File.separator + + "test-classes" + File.separator + "fediz_config_wreq.xml"); + cxt.getPipeline().addValve(fa); + + + rpServer.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @AfterClass + public static void cleanup() { + try { + if (idpServer.getServer() != null + && idpServer.getServer().getState() != LifecycleState.DESTROYED) { + if (idpServer.getServer().getState() != LifecycleState.STOPPED) { + idpServer.stop(); + } + idpServer.destroy(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + try { + if (rpServer.getServer() != null + && rpServer.getServer().getState() != LifecycleState.DESTROYED) { + if (rpServer.getServer().getState() != LifecycleState.STOPPED) { + rpServer.stop(); + } + rpServer.destroy(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getIdpHttpsPort() { + return idpHttpsPort; + } + + public String getRpHttpsPort() { + return rpHttpsPort; + } + + public String getServletContextName() { + return "fedizhelloworld"; + } + + @Test + public void testEntityExpansionAttack() throws Exception { + String url = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld/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"); + + FileInputStream is = new FileInputStream("src/test/resources/entity.xml"); + String entity = IOUtils.toString(is); + String reference = "&m;"; + + for (DomElement result : results) { + if ("wresult".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); + } + } + + // Invoke back on the RP + + final HtmlForm form = idpPage.getFormByName("signinresponseform"); + final HtmlSubmitInput button = form.getInputByName("_eventId_submit"); + + try { + button.click(); + Assert.fail("Failure expected on an entity expansion attack"); + } catch (FailingHttpStatusCodeException ex) { + ex.printStackTrace(); + // expected + Assert.assertTrue(ex.getMessage().contains("401 Unauthorized") + || ex.getMessage().contains("401 Authentication Failed") + || ex.getMessage().contains("403 Forbidden")); + } + + } + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/a5f80c99/systests/tomcat7/src/test/resources/entity.xml ---------------------------------------------------------------------- diff --git a/systests/tomcat7/src/test/resources/entity.xml b/systests/tomcat7/src/test/resources/entity.xml new file mode 100644 index 0000000..c0ff502 --- /dev/null +++ b/systests/tomcat7/src/test/resources/entity.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE RequestSecurityTokenResponseCollection [<!ENTITY a "1234567890" > + +<!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;" > + +<!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;" > + +<!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;" > + +<!ENTITY e "&d;&d;&d;&d;&d;&d;&d;&d;" > + +<!ENTITY f "&e;&e;&e;&e;&e;&e;&e;&e;" > + +<!ENTITY g "&f;&f;&f;&f;&f;&f;&f;&f;" > + +<!ENTITY h "&g;&g;&g;&g;&g;&g;&g;&g;" > + +<!ENTITY i "&h;&h;&h;&h;&h;&h;&h;&h;" > + +<!ENTITY j "&i;&i;&i;&i;&i;&i;&i;&i;" > + +<!ENTITY k "&j;&j;&j;&j;&j;&j;&j;&j;" > + +<!ENTITY l "&k;&k;&k;&k;&k;&k;&k;&k;" > + +<!ENTITY m "&l;&l;&l;&l;&l;&l;&l;&l;" > ]> \ No newline at end of file
