I want to give the user the possibility of writing symbolic maths formulas which are later evaluated with certain values.
The user might – for example – want to enter some formula a * (b + 1)
where a
and b
may be different upon each evaluation. My approach so far was using the built in JavaScript engine in Java but as I read through this tutorial on scripting, I realized that the engine is actually really powerful.
The formulas are stored in configuration files, so someone might send such a configuration file to another user, which would then be executed on their machine. Unfortunately I don’t know JavaScript, so I don’t know if the user could actually inject any seriously malicious code.
The formula above would be stored as a JavaScriptFormulaProcessor
object like this:
JavaScriptFormulaProcessor processor = new JavaScriptFormulaProcessor("a * (b + 1)", "a", "b");
Initializing the engine:
public JavaScriptFormulaProcessor(String formula, String... variableNames) throws ScriptException { ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript"); StringBuilder builder = new StringBuilder(variableNames[0]); for (int i = 1; i < variableNames.length; i++) { builder.append(", ").append(variableNames[i]); } String script = "function f("+builder.toString()+") { return "+formula+"}"; engine.eval(script); invocable = (Invocable) engine; }
Executing the function:
public void execute(Number[] functionInputs) throws ScriptException { try { Object result = invocable.invokeFunction("f", functionInputs); // process result.. } catch (NoSuchMethodException e) { throw new RuntimeException(e); // should actually never be thrown.. } }
Does this code create an attack vector for my application? Bonus question: if yes, any better suggestions?
Advertisement
Answer
If formula
is under the users’ control, then this code is extremely vulnerable because Java methods can be accessed and run from within the ScriptEngine
.
See also this question: Why can you execute Java-Code from a JS-ScriptEngine eval(String)?
As an example, consider this formula:
String formula = "(java.lang.Runtime.getRuntime().exec('some-malicious-script'), a+b)";
Apart from calculating the sum, this script would run java.lang.Runtime.getRuntime().exec()
.
You can run any static Java method this way.