2012-04-18 38 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