在Java中将用户输入评估为JavaScript时存在安全风险

时间:2016-02-17 10:46:27

标签: javascript java security code-injection symbolic-math

我想让用户有可能编写符号数学公式,这些公式稍后会用某些值进行评估。

用户可能 - 例如 - 想要输入一些公式a * (b + 1),其中ab在每次评估时可能会有所不同。到目前为止,我的方法是在Java中使用内置的JavaScript引擎,但在我阅读this tutorial on scripting时,我意识到引擎实际上非常强大。

公式存储在配置文件中,因此有人可能会将此类配置文件发送给另一个用户,然后在其计算机上执行。 不幸的是,我不了解JavaScript,所以我不知道用户是否真的可以注入任何严重的恶意代码。

上面的公式将存储为JavaScriptFormulaProcessor对象,如下所示:

JavaScriptFormulaProcessor processor =
        new JavaScriptFormulaProcessor("a * (b + 1)", "a", "b");

初始化引擎:

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;
}

执行功能:

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..
    }
}

此代码是否为我的应用程序创建了攻击媒介?奖金问题:如果是,还有更好的建议吗?

2 个答案:

答案 0 :(得分:1)

我想说这段代码不安全,因为你允许引擎评估JavaScript。

我会做什么: 将配置文件发送到服务器,接收器从中获取配置文件。编写一个解析器服务器端,它只接受有效的公式并丢弃任何不是的东西,然后将它存储在某个地方(数据库/文件/其他)。然后发送一个100%安全的包,你在解析到接收器后自己做了。通过这种方式,您可以确保接收器获得的任何信息都是由您首先验证的。

注意:如果你这样做,你需要在javascript中编写某种转换器,将你的包转换为javascript - 公式,以便通过你在问题中提供的代码来评估它。您可以选择仅验证服务器端,然后只发送最初发送给接收方的用户自制软件包,尽管您自己在验证时会犯错误导致接收方仍然运行不安全的代码。

答案 1 :(得分:0)

如果formula受用户控制,则此代码极易受攻击,因为可以从ScriptEngine内部访问和运行Java方法。

另请参阅以下问题:Why can you execute Java-Code from a JS-ScriptEngine eval(String)?

作为示例,请考虑以下公式:

String formula = "(java.lang.Runtime.getRuntime().exec('some-malicious-script'), a+b)";

除了计算总和,此脚本还将运行java.lang.Runtime.getRuntime().exec()。 您可以通过这种方式运行任何静态Java方法。