2012-04-18 57 views
3

我正在制作一个AJAX聊天室,指导我使用JSON和eval()函数。 这个聊天室具有正常的聊天功能和白板功能。 当一个正常的文本消息来自JSON格式的PHP服务器时,浏览器中的javascript会这样做:Javascript json eval()注入

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

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

With 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的drawLine的(200345222333),他被注射redirectToMyVirusSite()。 eval()将在聊天室中的每个人的浏览器中为他运行。 因此,正如你所看到的,让评估者从聊天室中的其他客户端执行命令显然是黑客邀请。我了解我所遵循的这本书只是为了介绍这些功能。在真实情况下,我们如何正确使用JSON来做到这一点?

例如是否有一个服务器端PHP或.NET功能javascriptencode /逃生,以确保没有黑客可以发送一个有效的JavaScript代码块到其他客户端的浏览器是eval()?或者可以安全地使用JSON eval(),它似乎是一个强大但邪恶的功能?

谢谢 汤姆

+5

把那本书扔掉。 – 2012-04-18 14:20:30

+2

这就是我讨厌网页开发书籍的原因。他们无法通过网络进行更改。 'eval()'=邪恶 – iambriansreed 2012-04-18 14:22:56

回答

8

这是什么书? 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) 
+0

同意。不要使用eval()。 – 2012-04-18 14:21:15

+0

O'Reilly的AJAX:1级...... – Tom 2012-04-18 14:21:54

+0

根据Angus Croll的说法,JSON.parse本身使用eval()。 https://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/ – Goose 2015-03-02 20:50:32

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()。尽管如此,您仍然需要正确解析和转发来自其他客户端的接收命令。但我建议找到一个没有eval的解决方案。

+0

1.代码重用了importServerNewMessagesSince()函数,并将author = svr_cmd作为特殊用户,其中'contents'字段包含javascript命令。 2.它在'contents'字段中接收白板命令drawLine(x,y,z,w),其中drawLine()是网页中的javascript函数。 eval(“drawLine(x,y,z,w)”)将直接执行该函数。 – Tom 2012-04-18 16:00:14

+0

不,问题是“服务器如何接收命令来画线?”。如果服务器收到一个javascript代码字符串,这不仅仅是一个攻击你的工具的邀请,它将是一个敞开大门! – Bergi 2012-04-18 17:00:21

1

将eval问题放在一边,不要在代码中使用可由用户填充的字段 - .author - 用于验证目的。将另一个字段添加到您的JSON消息中,如.is_server_command,如果存在,则表示消息的特殊处理。这个字段不会依赖用户输入,因此不会被“黑客”劫持。

+0

作者是用户的“显示名称”。谁输入了信息和/或谁在白板上绘制图片。我从书中复制并粘贴它。只想让核心工作,然后来到会员的东西。我是json的新手。复制代码中的eval()函数引起了我的注意。所以我就此发了一篇文章。 – Tom 2012-04-18 14:53:52

+0

是的。正是因为用户决定在这个领域将会发生什么,你不能将它用于那些应该只由你的服务器决定的东西。 – 2012-04-18 14:55:51

+0

“特殊”用户名可以是SVR_CMD,它可以是“34ee52aa3457ff”或任何标记。当发出白板绘图命令时,该ID将暴露给任何打开查看源代码的人。所以黑客总是可以复制该令牌并模仿服务器命令。我的观点是,问题似乎是eval()过于强大,可以从用户注入执行一段代码。 – Tom 2012-04-18 15:00:45