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());
+ }
+
+}