2012-04-18 17 views
3

JSONとeval()関数を使用するように教えてくれたAJAXの本の案内でAJAXチャットルームを作っています。 このチャットルームは通常のチャット機能とホワイトボード機能を備えています。 通常のテキストメッセージがJSON形式のPHPサーバから来た場合、ブラウザのJavaScriptはこれを行います:Javascript json eval()injection

ホワイトボードコマンドなし--------------------- ----------------------

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に自分のユーザー名を変更した場合、そのメッセージの入力にJavaScriptコードを入力し始める、drawLine(200345222333)のinsdead、彼は)(redirectToMyVirusSiteを注入されます。 eval()はチャットルームの全員のブラウザで彼のために実行します。 これから明らかなように、evalにチャットルーム内の他のクライアントからのコマンドを実行させることは、明らかにハッカーの招待です。私が従った本は機能の紹介であることを理解しています。 JSONを実際の状況で正しく行うにはどうすればよいですか?

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

ありがとう、 トム

+5

この本を投げ捨ててください。 –

+2

それは私がWeb開発の本について嫌いなものです。彼らはウェブで変わることはできません。 'eval()' = evil – iambriansreed

答えて

8

この本は何ですか? evalは悪ですが、それを使用する理由はひとつもありません。意味

var obj = JSON.parse(latest) 

あなたがして使用することができます:

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

が反対を行うには(JavaScriptのオブジェクトを - >

はjavascriptオブジェクトにJSON文字列を変換するには、次が行うことができますJSON文字列)の場合、次のように動作します。

var json = JSON.stringify(obj) 
+0

合意しました。 eval()は使わないでください。 –

+0

O'Reilly's AJAX:Level 1 ... – Tom

+0

Angus Crollによると、JSON.parseはeval()自体を使用しています。 https://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/ – Goose

3

実行コードが遺伝子他のクライアントによって評価され、サーバーでは評価されません。もちろん、誰がその名前を使用しないようにする必要がありますが、「著者」フィールドを使用する理由はわかりません。 {"author":"SVR_CMD","contents":"drawLine(x,y,z)"}の代わりにオブジェクト{"whiteboard":"drawLine(x,y,z)"}を送信してください。

しかし、eval()は依然としてハッカーの招待状です。無効なデータを送信して、出力に多かれ少なかれ直接影響を与えることができます。エスケープするための唯一の方法は、送受信したいデータ(図面データ)を適切にシリアル化することです。ホワイトボードのコマンドをどのように受け取るのですか? javascriptコードを "クリーン"にするためのサーバサイドの "エスケープ"機能はありません。常にセキュリティホールになります。

私はあなたがコマンド(ここでは "drawline")サニタイズすることができます

message = { 
    "author": "...", // carry the information /who/ draws 
    "whiteboard": { 
     "drawline": [200, 345, 222, 333] 
    } 
} 

のような直列化を期待するeasiliyを。

非常に複雑なコマンドがあり、転送されたデータをサーバー側に構築して縮小する場合は、eval()を使用すると問題ありません。それでも、受信したコマンドを他のクライアントから適切に解析してエスケープする必要があります。しかし、評価なしのソリューションを見つけることをお勧めします。

+0

1.コードはimportServerNewMessagesSince()関数を再利用し、author = svr_cmdを 'contents'フィールドにjavascriptコマンドがある特別なユーザーとして扱います。 2. drawLine()がウェブページのjavascript関数である 'contents'フィールドで、ホワイトボードコマンドdrawLine(x、y、z、w)を受け取ります。 eval( "drawLine(x、y、z、w)")は関数を直接実行します。 – Tom

+0

いいえ、問題は「サーバーが回線を引き出すコマンドをどのように受け取るのですか」でした。サーバーがJavaScriptコード文字列を受け取った場合、これはあなたのツールをハックするための招待状ではなく、大きな開きのドアになります! – Bergi

1

評価の問題を脇に置いて、認証のためにユーザーが入力できるフィールド(コード内に.author)を使用しないでください。別のフィールドをJSONメッセージに追加します。たとえば、.is_server_commandと指定すると、メッセージの特別な扱いを意味します。このフィールドはユーザーの入力に依存しないため、 "ハッカー"によってハイジャックされることはありません。

+0

authorは、ユーザーの「表示名」です。誰がメッセージを入力したのか、そして/または誰がホワイトボードに絵を描くのか。私は本からコピーして貼り付けた。コアだけをメンバーシップに利用したいと思っていました。私はjsonには新しいです。コピーされたコードのeval()関数が私の注意を引いた。だから、私はそれについて投稿しました。 – Tom

+0

はい。ユーザーがこのフィールドに何が入るかを決めるのは間違いなく、サーバーだけで決定されるものには使用できません。 –

+0

"特別な"ユーザー名にはSVR_CMDを使用できます。 "34ee52aa3457ff"または任意のトークンにすることができます。ホワイトボードの描画コマンドが発行されると、このIDはソースコードを表示するために開いた人に公開されます。したがって、ハッカーは常にそのトークンをコピーしてサーバーコマンドを模倣することができます。私の指摘は、問題はeval()があまりにも強力で、ユーザーインジェクションからコードを実行できるということです。 – Tom