package testcode.script;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateAwareExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
/**
* <h3>Why do the test cases need 3 very _similar_ block of code?</h3>
* <p>Because each of those function have distinct bytecode used for the call to "parseExpression()".
* One calling the interface, the abstract class and finally the concrete class. We don't want to miss any of the
* implementations.</p>
*/
public class SpelSample {
private static PersonDTO TEST_PERSON = new PersonDTO("Benoit", "Doudou");
public static void parseExpressionInterface(String property) {
ExpressionParser parser = new SpelExpressionParser();
//Static value not that useful .. but safe
Expression exp1 = parser.parseExpression("'safe expression'");
String constantValue = exp1.getValue(String.class);
System.out.println("exp1="+constantValue);
StandardEvaluationContext testContext = new StandardEvaluationContext(TEST_PERSON);
//Unsafe if the input is control by the user..
Expression exp2 = parser.parseExpression(property+" == 'Benoit'");
String dynamicValue = exp2.getValue(testContext, String.class);
System.out.println("exp2="+dynamicValue);
}
public static void parseSpelExpression(String property) {
SpelExpressionParser parser = new SpelExpressionParser();
//Static value not that useful .. but safe
Expression exp1 = parser.parseExpression("'safe expression'");
String constantValue = exp1.getValue(String.class);
System.out.println("exp1="+constantValue);
StandardEvaluationContext testContext = new StandardEvaluationContext(TEST_PERSON);
//Unsafe if the input is control by the user..
Expression exp2 = parser.parseExpression(property+" == 'Benoit'");
String dynamicValue = exp2.getValue(testContext, String.class);
System.out.println("exp2=" + dynamicValue);
}
public static void parseTemplateAwareExpression(String property) {
TemplateAwareExpressionParser parser = new SpelExpressionParser();
//Static value not that useful .. but safe
Expression exp1 = parser.parseExpression("'safe expression'");
String constantValue = exp1.getValue(String.class);
System.out.println("exp1="+constantValue);
StandardEvaluationContext testContext = new StandardEvaluationContext(TEST_PERSON);
//Unsafe if the input is control by the user..
Expression exp2 = parser.parseExpression(property+" == 'Benoit'");
String dynamicValue = exp2.getValue(testContext, String.class);
System.out.println("exp2="+dynamicValue);
}
public static void main(String[] args) {
//Expected use case..
parseExpressionInterface("firstName");
//Malicious use case..
parseExpressionInterface("T(java.lang.Runtime).getRuntime().exec('calc.exe')"); //start the calc virus :)
}
static class PersonDTO {
public final String firstName;
public final String lastName;
public PersonDTO(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
}