1

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?

Neuron
  • 5,141
  • 5
  • 38
  • 59
  • 2
    According to this article: http://andreas.haufler.info/2013/12/how-to-write-one-of-fastest-expression.html, there are a lot of implementations that do what u need without JS. – user3707125 Feb 17 '16 at 12:25
  • this makes me feel kinda stupid. I spent so much time searching for symbolic math libraries and I didn't find anything useful, while this article lists 6 possibilities! I guess I will stop writing my own implementation and just quietly bin it.. – Neuron Feb 17 '16 at 12:36
  • 1
    This does not seem like a good idea. If I understand it correctly, Java uses Mozilla Rhino as JavaScript engine and that allows [scripting Java](https://developer.mozilla.org/en-US/docs/Scripting_Java) as well. So you effectively allow your users to run arbitrary Java code on your server. – Gumbo Feb 18 '16 at 19:09

2 Answers2

1

I would say that this code is not safe as you allow JavaScript to be evaluated by the engine.

What I would do: Send the config file to a server, where the receiver gets the config file from. Write a parser server side that only accepts valid formulas and discards anything that isn't, then store it somewhere (database / file / whatever). Then send a 100% safe package that you made yourself after parsing to the receiver. This way you assure that whatever the receiver gets is firstly validated by you.

NOTE: If you do this, you need to write some sort of converter in javascript that converts your package to the javascript - formulas in order for it to be evaluated by the code that you present in your question. You could choose to only validate server side, and then just send the user-made package originally sent to the receiver, though you'd allow yourself to make a mistake in validating causing the receiver to still run unsafe code.

Glubus
  • 2,819
  • 1
  • 12
  • 26
  • Thanks for your time, but I am aware (as stated) that this enables users to inject code into my application. I would rather know *why* and *how* this is not safe. Also thank you for the suggestion, but 1) there is no central server, 2) if I have an algorithm for validating the code, I could as well run it on the users machine and 3) not knowing JavaScript, writing such a validator is probably not really the safest approach. – Neuron Feb 17 '16 at 12:35
  • Ah well the reason this is not safe is because you're doing this `engine.eval(script);`. So I could put javascript in there that for instance scans my targets computer for data and send it to my server. Or worse, generate form elements that fool my target into filling out sensitive data. Point 2) that you're making was part of my answer before I removed it, as it is not safe. You forget that an attacker also has access to this validation code, and can therefor find a way (if it exists) to get his code through your validation. – Glubus Feb 17 '16 at 12:41
1

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.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Alex Shesterov
  • 26,085
  • 12
  • 82
  • 103