3

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

没有白板命令 -------------------------------------------

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 稍作更改:

使用白板命令 ----------------------------------------------------------- ---

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 代码,而不是 drawLine(200,345,222,333),他正在注入 redirectToMyVirusSite()。eval() 只会在聊天室中每个人的浏览器中为他运行它。因此,如您所见,让 eval 执行聊天室中其他客户端的命令显然是黑客邀请。我知道我所遵循的这本书只是对功能的介绍。在实际情况下,我们如何正确使用 JSON?

例如,javascriptencode/escape 是否有服务器端 php 或 .net 函数,以确保没有黑客可以将有效的 javascript 代码发送到其他客户端的浏览器作为 eval() ?或者使用 JSON eval() 是否安全,它似乎是一个强大但邪恶的功能?

谢谢你,汤姆

4

3 回答 3

9

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

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

var obj = JSON.parse(latest)

这意味着您可以使用:

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

做相反的事情(javascript对象-> JSON字符串),以下工作:

var json = JSON.stringify(obj)
于 2012-04-18T14:19:03.083 回答
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”)。

eval()如果您有非常复杂的命令并希望通过在服务器端构建它们来减少传输的数据,则使用可能是可以的。尽管如此,您仍需要正确解析和转义从其他客户端接收到的命令。但我建议在没有评估的情况下找到解决方案。

于 2012-04-18T14:28:48.610 回答
1

撇开 eval 问题不谈,不要使用用户可以填写的字段 -.author在您的代码中 - 用于身份验证。将另一个字段添加到您的 JSON 消息中,例如.is_server_command当存在时,将表示对消息的特殊处理。该字段将不依赖于用户输入,因此不会被“黑客”劫持。

于 2012-04-18T14:32:16.913 回答