3

JSONとeval()関数の使い方を教えてくれるAJAXブックのガイダンスでAJAXチャットルームを作っています。このチャットルームには、通常のチャット機能とホワイトボード機能があります。通常のテキストメッセージが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));
    }   ...

ホワイトボードの描画コマンドは、「SVR_CMD」と呼ばれる特別なユーザー名でJSON形式でサーバーから送信されます。現在、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に変更した場合、メッセージ入力で、drawLine(200,345,222,333)の代わりにjavascriptコードの入力を開始し、redirectToMyVirusSite()を挿入します。eval()は、チャットルームの全員のブラウザで彼のためにそれを実行します。したがって、ご覧のとおり、チャットルームで他のクライアントからのコマンドをevalに実行させることは、明らかにハッカーの招待です。私がフォローした本は、機能の紹介にすぎないことを理解しています。実際の状況でJSONを使用して適切に行うにはどうすればよいですか?

たとえば、ハッカーが有効なjavascriptコードを他のクライアントのブラウザに送信してeval()にできないようにするために、javascriptencode / escapeにサーバー側のphpまたは.net関数がありますか?または、JSON eval()を使用しても安全ですか?それは強力ですが邪悪な関数のようです?

ありがとう、トム

4

3 に答える 3

9

この本は何ですか?eval悪であり、これを使用する理由は 1 つもありません。

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 に答える