Blocks ognl access to class members of Spring proxy

This commit is contained in:
Yasser Zamani
2017-06-13 18:48:23 +04:30
parent 843693fdd4
commit 2a8a6869d0
3 changed files with 58 additions and 3 deletions
@@ -15,12 +15,14 @@
*/
package com.opensymphony.xwork2.ognl;
import com.opensymphony.xwork2.util.ProxyUtil;
import ognl.DefaultMemberAccess;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.lang.reflect.*;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -85,6 +87,11 @@ public class SecurityMemberAccess extends DefaultMemberAccess {
return false;
}
if (isProxyAccess(target, member)) {
LOG.warn("Access to proxy [{}] is blocked!", member);
return false;
}
boolean allow = true;
if (!checkStaticMethodAccess(member)) {
LOG.warn("Access to static [{}] is blocked!", member);
@@ -100,6 +107,23 @@ public class SecurityMemberAccess extends DefaultMemberAccess {
return super.isAccessible(context, target, member, propertyName) && isAcceptableProperty(propertyName);
}
protected boolean isProxyAccess(Object target, Member member) {
if (!ProxyUtil.isSpringAopProxy(target))
return false;
Class<?> clazz = ProxyUtil.springUltimateTargetClass(target);
if (member instanceof Method) {
return null == MethodUtils.getMatchingMethod(clazz, member.getName(), ((Method) member).getParameterTypes());
}
if (member instanceof Field) {
return null == FieldUtils.getField(clazz, member.getName(), true);
}
if (member instanceof Constructor) {
return false;
}
return true;
}
protected boolean checkStaticMethodAccess(Member member) {
int modifiers = member.getModifiers();
if (Modifier.isStatic(modifiers)) {
@@ -5,8 +5,13 @@ package com.opensymphony.xwork2.spring;
import com.opensymphony.xwork2.*;
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.struts2.dispatcher.HttpParameters;
import org.springframework.context.ApplicationContext;
import java.util.HashMap;
import java.util.Map;
/**
* Test loading actions from the Spring Application Context.
*
@@ -100,4 +105,26 @@ public class ActionsFromSpringTest extends XWorkTestCase {
assertEquals(1, chaintoAOPedAction.getCount());
assertEquals("WW-4105", chaintoAOPedAction.getName());
}
public void testProxiedActionIsNotAccessible() throws Exception {
// given
Map<String, Object> params = new HashMap<>();
params.put("exposeProxy", "true");
params.put("issueId", "S2-047");
HashMap<String, Object> extraContext = new HashMap<>();
extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
ActionProxy proxy = actionProxyFactory.createActionProxy(null,
"chaintoAOPedTestSubBeanAction", null, extraContext);
// when
proxy.execute();
Object action = proxy.getAction();
//then
assertEquals("S2-047", ((TestSubBean) action).getIssueId());
assertFalse("proxied action is accessible!",
(boolean) MethodUtils.invokeMethod(action, "isExposeProxy"));
}
}
@@ -12,7 +12,9 @@
<interceptors>
<interceptor name="chain"
class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"></interceptor>
class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="params"
class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
</interceptors>
<action name="simpleAction" class="simple-action"/>
@@ -36,7 +38,9 @@
<action name="chaintoAOPedTestSubBeanAction" class="pointcutted-test-sub-bean"
method="getIssueId">
<interceptor-ref name="chain" />
<interceptor-ref name="params" />
<result name="WW-4105" type="null" />
<result name="S2-047" type="null" />
</action>
</package>
</xwork>