-
Notifications
You must be signed in to change notification settings - Fork 811
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WW-5343 Make SecurityMemberAccess an extensible bean #791
Conversation
@@ -133,7 +134,6 @@ public class DefaultConfiguration implements Configuration { | |||
Map<String, Object> constants = new HashMap<>(); | |||
constants.put(StrutsConstants.STRUTS_DEVMODE, Boolean.FALSE); | |||
constants.put(StrutsConstants.STRUTS_OGNL_LOG_MISSING_PROPERTIES, Boolean.FALSE); | |||
constants.put(StrutsConstants.STRUTS_OGNL_ENABLE_EVAL_EXPRESSION, Boolean.FALSE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This constant is not required for bootstrapping
} | ||
|
||
private static Set<String> toClassesSet(String newDelimitedClasses) throws ConfigurationException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved these utility methods into their own class
private boolean enableEvalExpression; | ||
|
||
private Set<String> excludedClasses = emptySet(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the configuration is now injected directly into SecurityMemberAccess
except for devMode configuration
public Set<String> getExcludedClasses() { | ||
return excludedClasses; | ||
return toClassesSet(container.getInstance(String.class, StrutsConstants.STRUTS_EXCLUDED_CLASSES)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deprecated getters are still functional for API compatibility
@@ -922,8 +855,7 @@ protected Map<String, Object> createDefaultContext(Object root, ClassResolver cl | |||
resolver = container.getInstance(CompoundRootAccessor.class); | |||
} | |||
|
|||
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticFieldAccess); | |||
memberAccess.disallowProxyMemberAccess(disallowProxyMemberAccess); | |||
SecurityMemberAccess memberAccess = container.getInstance(SecurityMemberAccess.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a prototype bean so will be a new instance per context
@@ -31,15 +31,19 @@ public interface MemberAccessValueStack { | |||
* @deprecated please use {@link #useExcludeProperties(Set)} | |||
*/ | |||
@Deprecated | |||
void setExcludeProperties(Set<Pattern> excludeProperties); | |||
default void setExcludeProperties(Set<Pattern> excludeProperties) { | |||
useExcludeProperties(excludeProperties); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lifted the deprecated implementations into the interface for cleanliness
@@ -234,6 +234,8 @@ public final class StrutsConstants { | |||
/** The name of the parameter to determine whether static field access will be allowed in OGNL expressions or not */ | |||
public static final String STRUTS_ALLOW_STATIC_FIELD_ACCESS = "struts.ognl.allowStaticFieldAccess"; | |||
|
|||
public static final String STRUTS_MEMBER_ACCESS = "struts.securityMemberAccess"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extension point!
@@ -31,33 +31,6 @@ public void setUp() throws Exception { | |||
ognlUtil = container.getInstance(OgnlUtil.class); | |||
} | |||
|
|||
public void testDefaultExcludes() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted tests whose functionality is covered elsewhere
* Test a raw OgnlValueStackFactory and OgnlValueStack generated by it | ||
* when no static access flags are set (not present in configuration). | ||
*/ | ||
public void testOgnlValueStackFromOgnlValueStackFactoryNoFlagsSet() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This flag is now a required constant so this test is no longer applicable
} | ||
|
||
@Test | ||
public void defaultExclusionList() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved/rewrote some tests here from OgnlUtilTest
core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
Outdated
Show resolved
Hide resolved
@@ -385,6 +386,7 @@ protected Container createBootstrapContainer(List<ContainerProvider> providers) | |||
builder.factory(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON); | |||
builder.factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON); | |||
builder.factory(OgnlUtil.class, Scope.SINGLETON); | |||
builder.factory(SecurityMemberAccess.class, Scope.PROTOTYPE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this is a good idea, attacker could get access to the SMA just by having access to the Container
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given it's prototype
scope, I don't believe it to make any difference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is, the container would return a new instance, and not the one that is being used by the ValueStack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant it will be possible creating a new instance via container
s methods, yet we excluded the whole package com.opensymphony.xwork2.inject
which means attacker cannot use container in the first place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, I also don't think there's anything useful an attacker can do with a fresh SecurityMemberAccess
instance
Kudos, SonarCloud Quality Gate passed! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm good but please update the docs to address that a new extension has been added (or at least update the ticket to inform users about it)
https://struts.apache.org/plugins/plugins-architecture#extension-points
Documentation PR is here: apache/struts-site#213 |
WW-5343
This will allow applications to easily extend the capabilities of
SecurityMemberAccess
. It additionally allows us to significantly simplify the configuration loading.