CodeQL documentation

Expression language injection (Spring)ยถ

ID: java/spel-expression-injection
Kind: path-problem
Security severity: 9.3
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-094
Query suites:
   - java-code-scanning.qls
   - java-security-extended.qls
   - java-security-and-quality.qls

Click to see the query in the CodeQL repository

The Spring Expression Language (SpEL) is a powerful expression language provided by the Spring Framework. The language offers many features including invocation of methods available in the JVM. If a SpEL expression is built using attacker-controlled data, and then evaluated in a powerful context, then it may allow the attacker to run arbitrary code.

The SpelExpressionParser class parses a SpEL expression string and returns an Expression instance that can be then evaluated by calling one of its methods. By default, an expression is evaluated in a powerful StandardEvaluationContext that allows the expression to access other methods available in the JVM.

Recommendationยถ

In general, including user input in a SpEL expression should be avoided. If user input must be included in the expression, it should be then evaluated in a limited context that doesnโ€™t allow arbitrary method invocation.

Exampleยถ

The following example uses untrusted data to build a SpEL expression and then runs it in the default powerful context.

public Object evaluate(Socket socket) throws IOException {
  try (BufferedReader reader = new BufferedReader(
      new InputStreamReader(socket.getInputStream()))) {

    String string = reader.readLine();
    ExpressionParser parser = new SpelExpressionParser();
    // BAD: string is controlled by the user
    Expression expression = parser.parseExpression(string);
    return expression.getValue();
  }
}

The next example shows how an untrusted SpEL expression can be run in SimpleEvaluationContext that doesnโ€™t allow accessing arbitrary methods. However, itโ€™s recommended to avoid using untrusted input in SpEL expressions.

public Object evaluate(Socket socket) throws IOException {
  try (BufferedReader reader = new BufferedReader(
      new InputStreamReader(socket.getInputStream()))) {

    String string = reader.readLine();
    ExpressionParser parser = new SpelExpressionParser();
    // AVOID: string is controlled by the user
    Expression expression = parser.parseExpression(string);
    SimpleEvaluationContext context 
        = SimpleEvaluationContext.forReadWriteDataBinding().build();
    // OK: Untrusted expressions are evaluated in a restricted context
    return expression.getValue(context);
  }
}

Referencesยถ

  • ยฉ GitHub, Inc.
  • Terms
  • Privacy