will evaluate one as an OGNL expression and will use its return value as another OGNL expression that it will evaluate with two as a root for the evaluation. So if one returns blah, then blah is evaluated as an OGNL statement.

CVE-2011-3923
Let's imagine we have an Action with a String parameter:

foo is normally set via HTTP parameter, e.g. '/myaction?foo=my+string' by evaluating HTTP parameter name (foo in this case) as an OGNL statement. All HTTP parameter names in Struts2 are OGNL statements and the way Struts2 prevents users from doing scary things like modifying session or calling methods comes down to 2 things:

Regular expression that all HTTP parameter names are checked against and which, for example, will not allow @ or # symbols, which are needed to call static methods or modify server-side objects like #session

OgnlContext (#context) properties whose values are checked before invoking methods and which are set to disallow method and static method execution by default. See CVE-2010-1870 for more info.

CVE-2011-3923 is the result of ParametersInterceptor allowing parentheses and thus allowing expression evaluation, which can be exploited as follows:

/myaction?foo=<OGNL statement>&(foo)('meh')=

and here's what happens:

Action attribute foo is set to the value of the foo HTTP parameter and will hold attacker's OGNL statement

Second HTTP parameter named(foo)('meh')will be evaluated as an expression evaluation OGNL statement and foo action attribute will be retrieved from the action (remember we control its value via HTTP parameter) and its value will be evaluated as another OGNL statement.

Since attacker's OGNL statement is in HTTP parameter value we bypass the regular expression and are allowed to use special symbols to modify OGNL context properties to allow method execution.