You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2013/10/18 08:47:32 UTC

svn commit: r1533336 - in /struts/struts2/trunk/core/src: main/java/org/apache/struts2/ main/java/org/apache/struts2/config/ main/java/org/apache/struts2/dispatcher/ main/java/org/apache/struts2/dispatcher/ng/ main/java/org/apache/struts2/security/ mai...

Author: lukaszlenart
Date: Fri Oct 18 06:47:31 2013
New Revision: 1533336

URL: http://svn.apache.org/r1533336
Log:
WW-4227 Adds first step to define internal security mechanism

Added:
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java
Modified:
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
    struts/struts2/trunk/core/src/main/resources/struts-default.xml

Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java Fri Oct 18 06:47:31 2013
@@ -268,4 +268,7 @@ public final class StrutsConstants {
     /** actions names' whitelist **/
     public static final String STRUTS_ALLOWED_ACTION_NAMES = "struts.allowed.action.names";
 
+    /** Security firewall **/
+    public static final String STRUTS_SECURITY_GATE = "struts.securityGate";
+
 }

Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java Fri Oct 18 06:47:31 2013
@@ -70,6 +70,7 @@ import org.apache.struts2.components.Url
 import org.apache.struts2.dispatcher.StaticContentLoader;
 import org.apache.struts2.dispatcher.mapper.ActionMapper;
 import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
+import org.apache.struts2.security.SecurityGate;
 import org.apache.struts2.views.freemarker.FreemarkerManager;
 import org.apache.struts2.views.util.UrlHelper;
 import org.apache.struts2.views.velocity.VelocityManager;
@@ -406,6 +407,8 @@ public class BeanSelectionProvider imple
 
         alias(TextParser.class, StrutsConstants.STRUTS_EXPRESSION_PARSER, builder, props);
 
+        alias(SecurityGate.class, StrutsConstants.STRUTS_SECURITY_GATE, builder, props);
+
         if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
             props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
             props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, "true");

Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java Fri Oct 18 06:47:31 2013
@@ -65,6 +65,7 @@ import org.apache.struts2.config.StrutsX
 import org.apache.struts2.dispatcher.mapper.ActionMapping;
 import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
 import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
+import org.apache.struts2.security.SecurityGate;
 import org.apache.struts2.util.AttributeMap;
 import org.apache.struts2.util.ObjectFactoryDestroyable;
 import org.apache.struts2.util.fs.JBossFileManager;
@@ -209,6 +210,7 @@ public class Dispatcher {
 
     private ValueStackFactory valueStackFactory;
 
+    private SecurityGate securityGate;
 
     /**
      * Create the Dispatcher instance for a given ServletContext and set of initialization parameters.
@@ -281,6 +283,11 @@ public class Dispatcher {
         this.handleException = Boolean.parseBoolean(handleException);
     }
 
+    @Inject
+    public void setSecurityGate(SecurityGate securityGate) {
+        this.securityGate = securityGate;
+    }
+
     /**
      * Releases all instances bound to this dispatcher instance.
      */
@@ -930,6 +937,15 @@ public class Dispatcher {
     }
 
     /**
+     * Checks if request doesn't contain suspicious values
+     *
+     * @param request current {@link HttpServletRequest}
+     */
+    public void checkRequest(HttpServletRequest request) {
+        securityGate.check(request);
+    }
+
+    /**
      * Provide an accessor class for static XWork utility.
      */
     public static class Locator {

Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ng/PrepareOperations.java Fri Oct 18 06:47:31 2013
@@ -158,6 +158,7 @@ public class PrepareOperations {
         ActionMapping mapping = (ActionMapping) request.getAttribute(STRUTS_ACTION_MAPPING_KEY);
         if (mapping == null || forceLookup) {
             try {
+                dispatcher.checkRequest(request);
                 mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, dispatcher.getConfigurationManager());
                 if (mapping != null) {
                     request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/DefaultSecurityGate.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,56 @@
+package org.apache.struts2.security;
+
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.StrutsConstants;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Default implementation of {@link org.apache.struts2.security.SecurityGate}
+ * just examines all the defined {@link org.apache.struts2.security.SecurityGuard}'s
+ */
+public class DefaultSecurityGate implements SecurityGate {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultSecurityGate.class);
+
+    private List<SecurityGuard> guards;
+    private boolean devMode;
+
+    @Inject(StrutsConstants.STRUTS_DEVMODE)
+    public void setDevMode(String devMode) {
+        this.devMode = "true".equalsIgnoreCase(devMode);
+    }
+
+    @Inject
+    public void setContainer(Container container) {
+        guards = new ArrayList<SecurityGuard>();
+        Set<String> guardNames = container.getInstanceNames(SecurityGate.class);
+        for (String guardName : guardNames) {
+            SecurityGuard guard = container.getInstance(SecurityGuard.class, guardName);
+            if (guard != null) {
+                guards.add(guard);
+            } else if (devMode) {
+                LOG.debug("Got null instance of [#0] for name [#1]", SecurityGuard.class.getSimpleName(), guardName);
+            }
+        }
+    }
+
+    public void check(HttpServletRequest request) {
+        for (SecurityGuard guard : guards) {
+            SecurityPass pass = guard.accept(request);
+            if (pass.isNotAccepted()) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("[#0] didn't accept the request!", guard.getClass().getName());
+                }
+                throw new StrutsSecurityException(pass.getGuardMessage());
+            }
+        }
+    }
+
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterNameSecurityGuard.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,14 @@
+package org.apache.struts2.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Checks if parameter name is valida and it doesn't contain vulnerable code
+ */
+public class ParameterNameSecurityGuard implements SecurityGuard {
+
+    public SecurityPass accept(HttpServletRequest request) {
+        return SecurityPass.accepted();
+    }
+
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/ParameterValueSecurityGuard.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,14 @@
+package org.apache.struts2.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Checks if parameter's value doesn't contain vulnerable code
+ */
+public class ParameterValueSecurityGuard implements SecurityGuard {
+
+    public SecurityPass accept(HttpServletRequest request) {
+        return SecurityPass.accepted();
+    }
+
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGate.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,12 @@
+package org.apache.struts2.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Main
+ */
+public interface SecurityGate {
+
+    void check(HttpServletRequest request);
+
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityGuard.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,12 @@
+package org.apache.struts2.security;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * TODO lukaszlenart: write a JavaDoc
+ */
+public interface SecurityGuard {
+
+    SecurityPass accept(HttpServletRequest request);
+
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/SecurityPass.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,36 @@
+package org.apache.struts2.security;
+
+/**
+ * TODO lukaszlenart: write a JavaDoc
+ */
+public class SecurityPass {
+
+    private Boolean accepted;
+    private final String message;
+
+    public static SecurityPass accepted() {
+        return new SecurityPass(true, null);
+    }
+
+    public static SecurityPass notAccepted(String message) {
+        return new SecurityPass(false, message);
+    }
+
+    private SecurityPass(boolean accepted, String message) {
+        this.accepted = accepted;
+        this.message = message;
+    }
+
+    public String getGuardMessage() {
+        return message;
+    }
+
+    public boolean isAccepted() {
+        return accepted;
+    }
+
+    public boolean isNotAccepted() {
+        return !accepted;
+    }
+
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/security/StrutsSecurityException.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,14 @@
+package org.apache.struts2.security;
+
+import org.apache.struts2.StrutsException;
+
+/**
+ * Exception indicates possible security breach
+ */
+public class StrutsSecurityException extends StrutsException {
+
+    public StrutsSecurityException(String message) {
+        super(message);
+    }
+
+}

Modified: struts/struts2/trunk/core/src/main/resources/struts-default.xml
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/struts-default.xml?rev=1533336&r1=1533335&r2=1533336&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/struts-default.xml (original)
+++ struts/struts2/trunk/core/src/main/resources/struts-default.xml Fri Oct 18 06:47:31 2013
@@ -134,6 +134,10 @@
     <bean type="ognl.PropertyAccessor" name="java.util.HashSet" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
     <bean type="ognl.PropertyAccessor" name="java.util.HashMap" class="com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor" />
 
+    <bean type="org.apache.struts2.security.SecurityGate" name="struts" class="org.apache.struts2.security.DefaultSecurityGate" scope="singleton"/>
+    <bean type="org.apache.struts2.security.SecurityGuard" name="parameterNameGuard" class="org.apache.struts2.security.ParameterNameSecurityGuard" scope="singleton"/>
+    <bean type="org.apache.struts2.security.SecurityGuard" name="parameterValueGuard" class="org.apache.struts2.security.ParameterValueSecurityGuard" scope="singleton"/>
+
     <package name="struts-default" abstract="true">
         <result-types>
             <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>

Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java (added)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterNameSecurityGuardTest.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,28 @@
+package org.apache.struts2.security;
+
+import com.mockobjects.servlet.MockHttpServletRequest;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class ParameterNameSecurityGuardTest {
+
+    @Test
+    public void shouldPass() throws Exception {
+        // given
+        SecurityGuard guard = new ParameterNameSecurityGuard();
+
+        HttpServletRequest request = new MockHttpServletRequest();
+
+        // when
+        SecurityPass pass = guard.accept(request);
+
+        // then
+        assertTrue(pass.isAccepted());
+        assertNull(pass.getGuardMessage());
+    }
+
+}

Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java?rev=1533336&view=auto
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java (added)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/security/ParameterValueSecurityGuardTest.java Fri Oct 18 06:47:31 2013
@@ -0,0 +1,28 @@
+package org.apache.struts2.security;
+
+import com.mockobjects.servlet.MockHttpServletRequest;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class ParameterValueSecurityGuardTest {
+
+    @Test
+    public void shouldPass() throws Exception {
+        // given
+        SecurityGuard guard = new ParameterValueSecurityGuard();
+
+        HttpServletRequest request = new MockHttpServletRequest();
+
+        // when
+        SecurityPass pass = guard.accept(request);
+
+        // then
+        assertTrue(pass.isAccepted());
+        assertNull(pass.getGuardMessage());
+    }
+
+}