假设您正在检查用户提供的操作数和操作符以确保它们包含所需的数据而不是其他JavaScript可执行代码,那么可以将两个操作数与操作符连接在一起,然后将其提供给eval()
以获得它执行。
现在,eval()
是危险,因为它可以执行任何JavaScript代码。用户可以在运营商和eval()
将评估它时提供可执行文件和可能的恶意JavaScript代码。因此,在进行连接时,应在验证操作数是否安全后执行此操作。为了强调这一点,我将写出一个大字体的计算机安全最重要的原则之一:
所有的输入是邪恶的,直到证明,否则。
此外,请注意,eval()
调用JavaScript解释器来解释,编译和执行您的代码。这很慢。虽然如果您偶尔使用eval()
,您可能没有注意到任何可观察到的性能问题,但如果您在每个关键事件上非常频繁地拨打eval()
,则可能会注意到性能问题。
考虑到这些缺陷eval()
,你可能想要找一个像Felix Kling发布的那样整齐的解决方案。但是,它也可以解决以安全的方式使用eval()
这个问题,如下图所示:
function compare(a, op, b)
{
// Check that we have two numbers and an operator fed as a string.
if (typeof a != 'number' || typeof b != 'number' || typeof op != 'string')
return
// Make sure that the string doesn't contain any executable code by checking
// it against a whitelist of allowed comparison operators.
if (['<', '>', '<=', '>=', '==', '!='].indexOf(op) == -1)
return
// If we have reached here, we are sure that a and b are two integers and
// op contains a valid comparison operator. It is now safe to concatenate
// them and make a JavaScript executable code.
if (eval(a + op + b))
doSomething();
}
注意验证对一个白名单输入几乎总是比它验证对黑名单更好的主意。请参阅https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet#White_List_Input_Validation对其进行简要讨论。
下面是该解决方案的演示:http://jsfiddle.net/YrQ4C/(代码也转载如下):
function doSomething()
{
alert('done something!')
}
function compare(a, op, b)
{
if (typeof a != 'number' || typeof b != 'number' || typeof op != 'string')
return
if (['<', '>', '<=', '>=', '==', '!='].indexOf(op) == -1)
return
if (eval(a + op + b))
doSomething();
}
// Positive test cases
compare(2, '<', 3)
compare(2, '<=', 3)
// Negative test cases
compare(2, '>', 3)
compare(2, '>=', 3)
// Attack tests
compare('alert(', '"attack!"', ')')
// Edit: Adding a new attack test case given by Jesse
// in the comments below. This function prevents this
// attack successfully because the whitelist validation
// for the second argument would fail.
compare(1, ';console.log("executed code");2==', 2)
编辑:演示与杰西的测试案例包括:http://jsfiddle.net/99eP2/
nope,你不能这样做在JS –