Fixed a security issue (see [1] for further details)

[1] https://cwiki.apache.org/confluence/display/WW/S2-009



git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/branches/STRUTS_2_3_X@1233422 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Maurizio Cucchiara
2012-01-19 15:13:03 +00:00
parent 150be4e3f7
commit 2c1eb6bb57
7 changed files with 55 additions and 10 deletions
+2 -2
View File
@@ -55,7 +55,7 @@
<distributionManagement>
<site>
<id>apache-site</id>
<url>scp://people.apache.org/www/struts.apache.org/2.3.1.1/</url>
<url>scp://people.apache.org/www/struts.apache.org/2.x/</url>
</site>
</distributionManagement>
@@ -85,7 +85,7 @@
<properties>
<currentVersion>${project.version}</currentVersion>
<struts2.springPlatformVersion>3.0.5.RELEASE</struts2.springPlatformVersion>
<ognl.version>3.0.3</ognl.version>
<ognl.version>3.0.4</ognl.version>
<asm.version>3.3</asm.version>
<tiles.version>2.0.6</tiles.version>
</properties>
@@ -135,7 +135,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
static boolean devMode = false;
// Allowed names of parameters
private String acceptedParamNames = "[a-zA-Z0-9\\.\\]\\[\\(\\)_']+";
private String acceptedParamNames = "\\w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['\\w+'\\])|(\\('\\w+'\\)))*";
private Pattern acceptedPattern = Pattern.compile(acceptedParamNames);
private ValueStackFactory valueStackFactory;
@@ -289,7 +289,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
String name = entry.getKey();
Object value = entry.getValue();
try {
newStack.setValue(name, value);
newStack.setParameter(name, value);
} catch (RuntimeException e) {
if (devMode) {
String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{
@@ -206,7 +206,23 @@ public class OgnlUtil {
* Ideally, this should be handled by OGNL directly.
*/
public void setValue(String name, Map<String, Object> context, Object root, Object value) throws OgnlException {
Ognl.setValue(compile(name), context, root, value);
setValue(name, context, root, value, true);
}
protected void setValue(String name, Map<String, Object> context, Object root, Object value, boolean evalName) throws OgnlException {
Object tree = compile(name);
if (!evalName && isEvalExpression(tree, context)) {
throw new OgnlException("Eval expression cannot be used as parameter name");
}
Ognl.setValue(tree, context, root, value);
}
private boolean isEvalExpression(Object tree, Map<String, Object> context) throws OgnlException {
if (tree instanceof SimpleNode) {
SimpleNode node = (SimpleNode) tree;
return node.isEvalChain((OgnlContext) context);
}
return false;
}
public Object getValue(String name, Map<String, Object> context, Object root) throws OgnlException {
@@ -245,7 +261,7 @@ public class OgnlUtil {
public void copy(Object from, Object to, Map<String, Object> context, Collection<String> exclusions, Collection<String> inclusions) {
if (from == null || to == null) {
if (LOG.isWarnEnabled()) {
LOG.warn("Attempting to copy from or to a null source. This is illegal and is bein skipped. This may be due to an error in an OGNL expression, action chaining, or some other event.");
LOG.warn("Attempting to copy from or to a null source. This is illegal and is bein skipped. This may be due to an error in an OGNL expression, action chaining, or some other event.");
}
return;
@@ -284,7 +300,7 @@ public class OgnlUtil {
copy = false;
}
if (copy == true) {
if (copy) {
PropertyDescriptor toPd = toPdHash.get(fromPd.getName());
if ((toPd != null) && (toPd.getWriteMethod() != null)) {
try {
@@ -144,6 +144,15 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
return root;
}
/**
* @see com.opensymphony.xwork2.util.ValueStack#setParameter(String, Object)
*/
public void setParameter(String expr, Object value) {
setValue(expr, value, devMode, false);
}
/**
/**
* @see com.opensymphony.xwork2.util.ValueStack#setValue(java.lang.String, java.lang.Object)
*/
@@ -155,9 +164,13 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
* @see com.opensymphony.xwork2.util.ValueStack#setValue(java.lang.String, java.lang.Object, boolean)
*/
public void setValue(String expr, Object value, boolean throwExceptionOnFailure) {
setValue(expr, value, throwExceptionOnFailure, true);
}
private void setValue(String expr, Object value, boolean throwExceptionOnFailure, boolean evalExpression) {
Map<String, Object> context = getContext();
try {
trySetValue(expr, value, throwExceptionOnFailure, context);
trySetValue(expr, value, throwExceptionOnFailure, context, evalExpression);
} catch (OgnlException e) {
handleOgnlException(expr, value, throwExceptionOnFailure, e);
} catch (RuntimeException re) { //XW-281
@@ -167,10 +180,10 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
}
}
private void trySetValue(String expr, Object value, boolean throwExceptionOnFailure, Map<String, Object> context) throws OgnlException {
private void trySetValue(String expr, Object value, boolean throwExceptionOnFailure, Map<String, Object> context, boolean evalExpression) throws OgnlException {
context.put(XWorkConverter.CONVERSION_PROPERTY_FULLNAME, expr);
context.put(REPORT_ERRORS_ON_NO_PROP, (throwExceptionOnFailure) ? Boolean.TRUE : Boolean.FALSE);
ognlUtil.setValue(expr, context, root, value);
ognlUtil.setValue(expr, context, root, value, evalExpression);
}
private void cleanUpContext(Map<String, Object> context) {
@@ -74,6 +74,14 @@ public interface ValueStack {
*/
public abstract void setValue(String expr, Object value);
/**
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
* N.B.: unlike #setValue(String,Object) it doesn't allow eval expression.
* @param expr the expression defining the path to the property to be set.
* @param value the value to be set into the named property
*/
void setParameter(String expr, Object value);
/**
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
*
@@ -50,6 +50,10 @@ public class StubValueStack implements ValueStack {
ctx.put(expr, value);
}
public void setParameter(String expr, Object value) {
throw new UnsupportedOperationException("not implemented");
}
public void setValue(String expr, Object value, boolean throwExceptionOnFailure) {
ctx.put(expr, value);
}
@@ -509,6 +509,10 @@ public class ParametersInterceptorTest extends XWorkTestCase {
public void setValue(String expr, Object value) {
actual.put(expr, value);
}
@Override
public void setParameter(String expr, Object value) {
actual.put(expr, value);
}
};
container.inject(stack);
return stack;