連載
» 2009年10月14日 00時00分 公開

教科書に載らないWebアプリケーションセキュリティ(5):[さらに気になる]JSONの守り方 (2/3)

[はせがわようすけ,ネットエージェント株式会社]

JSON評価時の危険性

 受け取ったJSON文字列を、JavaScriptのオブジェクトとして扱うためにevalを使うと説明しましたが、万が一JSONデータ内に、攻撃者の仕組んだスクリプト相当の文字列が含まれていた場合、evalを使うとJavaScriptとしてそのまま実行してしまうため、大変危険です。

 例えば、以下のようなJSONが生成されたとします。太字部分が攻撃者の用意したデータです。

{ "name" : ""};alert(document.cookie);//"}

 これをそのままevalで評価すると、alert(document.cookie)も動作してしまいます。

 対策としてはJSONによるXSS同様、文字列内の半角英数字以外をすべて\uXXXXの形式でエスケープすることなのですが、後述するXMLHttpRequest Level 2などを用い、クロスドメインで他者の用意したJSONを読み込んだ場合には、正しくエスケープされていることが保証されません。そのため、内容を確認せずにevalするのは相当危険が伴うかもしれません。

 そのような問題を解決するためのライブラリとして、json2.jsが広く使われています。このjson2.jsを使用すれば、いきなりevalでJSONを評価するのではなく、JSON内の各要素を確認しながらオブジェクトが生成されますので、安全にJSONデータを扱うことができます。

 また、Firefox 3.5、Google Chrome 3、Safari 4、IE8(IE8標準モードのみ)では、json2.js互換のJSON.parseなどがネイティブにサポートされているため、より高速にJSONデータを安全に解釈することができます。

 このように、JSONにもさまざまな危険性が潜んでいますが、正しく使用すれば非常に使い勝手のいいデータ形式ですので、ぜひうまく利用したいものです。

クロスドメインでのデータアクセス

 前回および今回で、JSONおよびJSONPを扱う上で発生する可能性のあるセキュリティ上の問題点および対策について説明しました。JSONPをうまく利用すればクロスドメインでのデータアクセスを実現できますが、これはSame Origin Policyを避けるためにJSONを細工したものであり、どうしても呼び出しの不自然さ、無理やり感は否めません。

 最近では、より自然にクロスドメインで通信を実現するための仕組みがいくつか提案、実装されていますので、それらを簡単に紹介します。

●XMLHttpRequest Level 2

 Ajaxの核であるXMLHttpRequestでは、これまでSame Origin Policyに基づき、ドメインを超えての通信ができませんでした。現在W3Cでは、クロスドメインでの通信を可能にしたXMLHttpRequest Level 2の仕様策定が進んでおり、すでにいくつかのブラウザでは、草案に基づいたXMLHttpRequest Level 2の実装がなされています。

 JavaScript側ではこれまでのXMLHttpRequestと同様のコードで、ほかのドメインに対するリクエストを発行することができます。

 // このスクリプトは example.jp上で動き、example.comに
// リクエストを発行するものとします。
if( window.XMLHttpRequest ){
var xhr = new XMLHttpRequest();
xhr.open( "get", "http://example.com/data.txt", true );
xhr.onreadystatechange = function(){
if( xhr.readyState == 4 && xhr.status == 200 ){
alert( xhr.responseText );
}
}
xhr.send( null );
}

 サーバ側では、クロスドメインでのアクセスを許可するリソースについては、レスポンスのAccess-Control-Allow-Originヘッダにて、アクセスを許可するリクエスト元のドメインを明示します。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.jp
Content-Type: text/plain; charset=utf-8
<テキストデータ>

 この例では、http://example.jp上で動くJavaScriptから、XMLHttpRequestを使ってexample.com上のリソースを読み込むことができます。

 「Access-Control-Allow-Origin: *」を指定すると、すべてのドメインからのリクエストを許可することになります。

 このように、使いなれたXMLHttpRequestをそのまま利用して、クロスドメインのデータアクセスを実現可能としたのがXMLHttpRequest Level 2です。現在、Firefox 3.5、Google Chrome 3、Safari 4などのブラウザでXMLHttpRequest Level 2が利用可能です。

●XDomainRequest

 一方、IE8ではXMLHttpRequest Level 2に代わり、XDomainRequest という機能が用意されました。このXDomainRequestでもXMLHttpRequestとよく似たコードで、JavaScript上でクロスドメインでの通信が実現できます。

 具体的なJavaScript側のコードは、以下のようになります。

 // このスクリプトはexample.jp上で動き、example.comに
// リクエストを発行するものとします。
if( window.XDomainRequest ){
var xdr = new XDomainRequest();
xdr.onerror = function(){
alert( "error" );
}
xdr.onloaded = function(){
alert( xdr.contentType + "\n" + xdr.responseText );
}
xdr.open( "get", "http://example.com/data.txt" );
xdr.send( null );
}

 サーバ側では、XMLHttpRequest Level 2と同じく、Access-Control-Allow-Originレスポンスヘッダを用いてアクセスを許可するドメインを明示します。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.jp
Content-Type: text/plain; charset=utf-8

<テキストデータ>

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。