【问题标题】:JavaScript to evaluate simple math string like 5*1.2 (eval/white-list?)JavaScript 评估简单的数学字符串,如 5*1.2 (eval/white-list?)
【发布时间】:2012-03-28 19:23:01
【问题描述】:

我有一个输入 onchange,可以将 05008 等数字转换为 5,008.00

我正在考虑对此进行扩展,以便进行简单的计算。例如,45*5 将自动转换为 225.00

我可以使用字符白名单()+/*-0123456789.,然后将结果传递给eval,我认为这些字符是安全的,可以防止任何危险的注入。假设我使用了适当的try/catch,因为可能会产生语法错误。

  • 这是一个 OK 白名单,然后将其传递给eval

  • 建议修改白名单

  • 您是否推荐一种不同的方法(也许已经有一个函数可以做到这一点)

    我宁愿保持轻量级。这就是我喜欢eval/white-list 方法的原因。代码很少。

你有什么推荐的?

【问题讨论】:

  • 您是否将原始输入传递给其他用户/数据库/其他地方?否则我不会担心用户注入自己。
  • 可能会为页面设计一个链接,导致填写自定义默认值。如果恶意的人让用户点击链接,我需要确保它不会t 将 javascript 代码注入我的页面,导致 XSS 攻击。我认为白名单可以,但我知道JavaScript can be done without letters,所以我想先由你们运行它。每当我这样做时,我经常会得到更好的想法。
  • 澄清一下,JavaScript 的工作是规范化输入。服务器只是拒绝任何意外。所以 服务器 不会在任何地方发送原始输入,直到它被转换为double - 没有任何花哨的解释,因为这都是在客户端完成的。服务器使用普通已知的安全解析,JavaScript 使用这个花哨的安全数学函数。

标签: javascript math onchange


【解决方案1】:

那个白名单看起来对我来说是安全的,但这不是一个简单的问题。例如,在某些浏览器中,像这样的 eval 字符串:

/.(.)/(34)

等价于:

new RegExp('.(.)').exec('34')

因此返回数组['34','4']。那是“安全的”吗?

因此,虽然这种方法可能可以安全地工作,但它可能是一个非常棘手的提议。如果您确实采用这个想法,我认为您应该使用更积极的方法来验证您的输入。您的原则应该是“这是一组明确定义且已知为‘安全’的字符串的成员”,而不是“这是一组定义不明确的字符串的成员,该字符串排除了所有已知为‘不安全’的字符串'”。此外,为了避免操作员偷看您没有考虑过的任何风险(例如+++= 或诸如此类),我认为您应该在每个非数字非点字符前插入一个空格;并且为了避免括号触发函数调用的任何风险,我认为您应该通过将(...) 反复替换为空格加上评估... 的结果(在确认该结果是一个数字之后)加上一个空格来自己处理它们。

(顺便说一句,= 怎么会在你的白名单中?我就是想不通它有什么用处!)

【讨论】:

  • 我相信它可能做的最糟糕的事情是通过运行一些效率低下的复杂正则表达式来冻结窗口。无论如何,我肯定会要求在斜线之前加上一个数字,以防止这种危险的事情发生。
【解决方案2】:

鉴于这个极其严格的白名单,除了抛出异常之外,我看不到任何执行恶意操作的方法。 bracket trick 不起作用,因为它需要方括号 []

也许最安全的选择是将页面的默认值解析器修改为只接受数字并丢弃其他任何内容。这样一来,链接中的潜在恶意代码将永远不会到达eval

这只留下了用户在字段中输入恶意内容的可能性,但是为什么还要担心呢?用户已经可以访问他们可以用来执行任意代码的控制台(开发工具)。

【讨论】:

    【解决方案3】:

    eval 一个经常被忽视的问题是它会导致 javascript minifiers 出现问题。

    像 YUI 之类的一些缩小器会在看到 eval 语句时采取安全路线并停止重命名变量。这意味着您的 javascript 可以工作,但您的压缩文件将比它需要的大。

    Google Closure Compiler 等其他工具会继续重命名变量,但如果您不小心,它们可能会破坏您的代码。您应该避免将带有变量名的字符串传递给 eval。例如。

    var input = "1+2*3";
    
    var result = eval("input"); // unsafe
    
    var result = eval(input); // safe
    

    【讨论】:

    • 您的第一点值得关注;我什至没有考虑过eval 的存在可能会影响缩小器。第二点稍微复杂一些。假设这是在函数内部发生的,eval("input") 根本不起作用,因为eval 代码在全局范围内运行;它无法访问函数的本地 input 变量。 (这很好;你可能不希望 input 成为全球性的。)
    猜你喜欢
    • 1970-01-01
    • 2011-08-27
    • 2018-01-15
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    • 2012-05-29
    相关资源
    最近更新 更多