Javascript json eval()注入

时间:2012-04-18 14:10:39

标签: javascript json eval code-injection

我正在制作一个AJAX聊天室,在AJAX书的指导下教我使用JSON和eval()函数。 这个聊天室具有正常的聊天功能和白板功能。 当普通文本消息来自JSON格式的php服务器时,浏览器中的javascript会执行以下操作:

没有白板命令------------------------------------------- < / p>

function importServerNewMessagesSince(msgid) {
    //loadText() is going to return me a JSON object from the server
    //it is an array of {id, author, message}
    var latest = loadText("get_messages_since.php?message=" + msgid);
    var msgs = eval(latest);
    for (var i = 0; i < msgs.length; i++) {
                    var msg = msgs[i];
                    displayMessage(escape(msg.id), escape(msg.author), escape(msg.contents));
    }   ...

白板绘图命令由服务器以JSON格式发送,使用名为“SVR_CMD”的特殊用户名,现在javascript略有改变:

使用Whiteboard Command -------------------------------------------- ------

function importServerNewMessagesSince(msgid) {
    //loadText() is going to return me a JSON object from the server
    //it is an array of {id, author, message}
    var latest = loadText("get_messages_since.php?message=" + msgid);
    var msgs = eval(latest);
    for (var i = 0; i < msgs.length; i++) {
                    var msg = msgs[i];
                    if (msg.author == "SVR_CMD") {

                        eval(msg.contents);  // <-- Problem here ...

                         //I have a javascript drawLine() function to handle the whiteboard drawing
                        //server command sends JSON function call like this: 
                        //"drawLine(200,345,222,333)" eval() is going to parse execute it
                        //It is a hacker invitation to use eval() as someone in chat room can
                        //insert a piece of javascript code and send it using the name SVR_CMD?

                   else {
                        displayMessage(escape(msg.id), escape(msg.author), escape(msg.contents));
                    }

    }   ...

现在,如果黑客在脚本中将其用户名更改为SVR_CMD,则在消息输入中开始输入javascript代码,insdead of drawLine(200,345,222,333),他正在注入redirectToMyVirusSite()。 eval()将在聊天室的每个人的浏览器中为他运行它。 因此,正如您所看到的,让eval从聊天室中的其他客户端执行命令显然是黑客邀请。我理解我所遵循的这本书只是为了介绍这些功能。在真实情况下我们如何使用JSON正确完成?

e.g。是否有一个服务器端php或.net函数到javascriptencode / escape,以确保没有黑客能够将有效的javascript代码发送到其他客户端的浏览器为eval()?或者根本不使用JSON eval(),它似乎是一个强大而又邪恶的功能?

谢谢你, 汤姆

3 个答案:

答案 0 :(得分:8)

这本书是什么? eval是邪恶的,永远没有一个理由可以使用它。

要将JSON字符串转换为javascript对象,您可以执行以下操作:

var obj = JSON.parse(latest)

这意味着您可以使用:

[].forEach.call(obj, function( o ) {
    // You can use o.message, o.author, etc.
} )

为了做相反的事情(javascript对象 - &gt; JSON字符串),以下工作:

var json = JSON.stringify(obj)

答案 1 :(得分:3)

如果执行的代码是由其他客户端而不是服务器生成的,那么它是不安全的。当然你需要阻止任何人使用该名称,虽然我不明白为什么你会使用“作者”字段?只需发送一个对象{"whiteboard":"drawLine(x,y,z)"}而不是{"author":"SVR_CMD","contents":"drawLine(x,y,z)"}

但它是对的,eval()仍然是黑客的邀请。人们总是可以发送无效数据并尝试或多或少地直接影响输出。转义的唯一方法是对要接收和发送的数据进行适当的序列化 - 图纸数据。你如何收到白板命令?没有服务器端“转义”功能,使javascript代码“干净” - 它永远是一个安全漏洞。

我希望像

这样的序列化
message = {
    "author": "...", // carry the information /who/ draws
    "whiteboard": {
         "drawline": [200, 345, 222, 333]
    }
}

所以你可以清理命令(这里:“drawline”)easiliy。

如果您有非常复杂的命令并希望通过在服务器端构建它们来减少传输的数据,则eval()的使用可能没问题。但是,您需要正确地解析并转义来自其他客户端的接收命令。但我建议找一个没有评估的解决方案。

答案 2 :(得分:1)

除了设置eval问题之外,请不要在代码中使用可由用户填写的字段 - .author - 用于身份验证。在JSON消息中添加另一个字段,比如.is_server_command,如果存在,则表示对消息的特殊处理。该字段不依赖于用户输入,因此不会被“黑客”劫持。