当它只执行服务器端数据时,在javascript中使用eval是否安全?

时间:2015-03-31 12:50:08

标签: javascript ajax eval

是的,它是this question的一个副本,但是@apsillers给出的答案是一个超级答案,因为它指出了问题的一个新方面,这在前一个问题中没有被告知。另一个有用的SO问题帮助我更好地解决了eval()安全问题究竟是什么that question

我在我的javascript代码中使用了eval(),我想知道是否应该让它失效。

Principe:我有一个ajax调用,初始化浏览器客户端和服务器之间的第一个连接。服务器运行PHP。规则是:当客户端发送变量' init'在请求中,在服务器端PHP获取必要脚本的内容,将每个脚本的内容作为对象中的新条目(值为内容,名称为没有扩展名的文件名,对象是PHP的实例) STD Class),用JSON转换整个对象(按惯例)并发送回所有内容。在客户端,当httprequest完成后,Javascript获取对象并对其执行简单的... in()。

每次出现时,我都有两个选择:要么将内容连接成一个手工制作的脚本标签,我将其注入HTML页面的 head 。或者我评估内容(我现在这样做)以便执行代码而无需使用 head 标记。它主要是为了审美。

以下是代码:

var xhr = null;

if (window.XMLHttpRequest || window.ActiveXObject) {
    ... //prepare the ajax request (initialize variable xhr)
}


var url = "index.php";
var params = "action=init";
xhr.open('POST', url, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(params);

xhr.onreadystatechange = function() {
       if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 0)) {
           var o = JSON.parse(xhr.responseText);


           for(s in o) eval(o[s]);


       }
}

我的问题:在这种情况下,我绝对应该避免使用eval吗?或者它是否足够安全(因为只有管理员能够修改动态注入的脚本)?

1 个答案:

答案 0 :(得分:1)

eval的安全规则是:用户永远不应eval由其他用户生成或修改的字符串。对服务器创建的eval字符串完全安全。毕竟,服务器正在提供页面的实际代码,因此如果它选择将该代码作为eval字符串提供,则不一定存在安全问题。

就安全性而言,包含动态创建的<script>元素与调用eval基本上一样危险(或基本上安全)。唯一的区别是<script>代码将始终在全局范围内运行,而eval可以在调用的词法范围内运行,允许它从其包含的函数访问变量。这可能是也可能不是,这取决于您希望脚本可以访问的内容。

function f() {
    var a = 5;
    eval("alert(a);");
    // an injected <script> wouldn't have access to `a`
}

eval带来的潜在危险是严格验证eval的内容从未被其他用户生成或修改过,可能非常困难。在您的情况下,如果Object.prototype已提供任何可枚举属性(包含在您的for..in循环中),则该属性的值将为eval ed:

Object.prototype.foo = "alert(1);";

您可以通过强制执行自己的属性检查来解决此问题:

for(var s in o) {
    if(o.hasOwnProperty(s)) {
        eval(o[s]);
    }
}

eval也会导致严重的性能损失并产生无法优化的可变范围情况,但这不是安全问题。