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

在Java中将用户输入评估为JavaScript时存在安全风险,javascript,java,security,code-injection,symbolic-math,Javascript,Java,Security,Code Injection,Symbolic Math,我想让用户能够编写符号数学公式,这些公式在以后使用某些值进行计算 例如,用户可能希望输入一些公式a*(b+1),其中a和b在每次评估时可能不同。到目前为止,我的方法是使用Java中内置的JavaScript引擎,但当我通读时,我意识到该引擎实际上非常强大 公式存储在配置文件中,因此有人可能会将这样的配置文件发送给另一个用户,然后在他们的机器上执行。 不幸的是,我不懂JavaScript,所以我不知道用户是否真的可以注入任何严重的恶意代码 上面的公式将存储为JavaScriptFormulaPro

我想让用户能够编写符号数学公式,这些公式在以后使用某些值进行计算

例如,用户可能希望输入一些公式
a*(b+1)
,其中
a
b
在每次评估时可能不同。到目前为止,我的方法是使用Java中内置的JavaScript引擎,但当我通读时,我意识到该引擎实际上非常强大

公式存储在配置文件中,因此有人可能会将这样的配置文件发送给另一个用户,然后在他们的机器上执行。 不幸的是,我不懂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..
    }
}

<这个代码是否为我的应用程序创建了一个攻击向量?附加问题:如果是,还有更好的建议吗?

我想说,这段代码不安全,因为您允许引擎对JavaScript进行评估

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


注意:如果您这样做,您需要用javascript编写某种转换器,将您的包转换为javascript公式,以便您在问题中提供的代码对其进行评估。您可以选择只验证服务器端,然后只将最初发送给接收者的用户制作的包发送给接收者,尽管您允许自己在验证时出错,导致接收者仍然运行不安全的代码。

如果
公式
不受用户控制,由于Java方法可以从
ScriptEngine
中访问和运行,因此该代码极易受到攻击

另见这个问题:

作为一个例子,考虑这个公式:

String formula = "(java.lang.Runtime.getRuntime().exec('some-malicious-script'), a+b)";
除了计算总和外,此脚本还将运行
java.lang.Runtime.getRuntime().exec()

您可以通过这种方式运行任何静态Java方法。

根据本文:,有很多实现可以在没有JS的情况下完成您需要的功能。这让我觉得有点愚蠢。我花了太多时间搜索符号数学库,但没有找到任何有用的东西,而本文列出了6种可能性!我想我会停止编写自己的实现,只是静静地把它扔掉。这似乎不是一个好主意。如果我理解正确的话,Java使用Mozilla Rhino作为JavaScript引擎,这也允许。因此,您可以有效地允许用户在您的服务器上运行任意Java代码。感谢您的时间,但我知道(如上所述),这允许用户将代码注入到我的应用程序中。我宁愿知道为什么这样做不安全,为什么这样做不安全。同样感谢您的建议,但是1)没有中央服务器,2)如果我有一个验证代码的算法,我也可以在用户机器上运行它,3)不知道JavaScript,编写这样的验证器可能不是最安全的方法。啊,这不安全的原因是因为你在做
engine.eval(script);
。这样我就可以把javascript放在那里,比如扫描目标计算机的数据并将其发送到服务器。或者更糟糕的是,生成表单元素欺骗目标填写敏感数据。在我删除它之前,你所做的第2点是我答案的一部分,因为这不安全。您忘记了攻击者也可以访问此验证代码,因此可以找到一种方法(如果存在的话)使其代码通过您的验证。