ここが危ない!Web2.0のセキュリティ

第1回Ajaxとクロスサイトスクリプティング

初回はWeb2.0の中核技術ともいえるAjaxを見ていきたいと思います。
Ajaxのセキュリティについて考えていきますが、その前にAjaxについて簡単におさらいしてみましょう。

AjaxとはAsynchronous JavaScript XMLの略であり、一言で言えばJavaScriptとXMLを使って非同期に通信するということです(XML以外の形式が使われることも多くなりました⁠⁠。通信を非同期にすることで、何か処理をする場合にいちいち待たなくても次の処理に移ることができます。その結果、ユーザを待たせずに多くの処理を行えるようになりました。また、画面全体を再読み込みする必要がなくなったことも、使い勝手の向上した理由です。

Ajaxの動作

それでは簡単なサンプルコードでAjaxの動作を見ていきたいと思いますリスト1⁠。これらはAjaxの入門サイトや書籍で一番最初に出てくるコードですので見たことのある方もいらっしゃると思います。

リスト1 Ajaxのサンプルコード
<script language="javascript">
  var req;
  if( window.XMLHttpRequest){
    req = new XMLHttpRequest();
  }else if(window.ActiveXObject){
    try {
      req = new ActiveXObject("MSXML2.XMLHTTP");
    } catch (e) {
      req = new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
  if (req) {
    req.open('GET', 'http://www.example.com/contents.txt');
    req.onreadystatechange = function() {
      if (req.readyState == 4) {
        document.write(req.responseText);
      }
    }
    req.send(null);
  }
</script>

contents.txtの内容

Hello Ajax.

index.htmlを開くとスクリプトが実行され、ブラウザはcontents.txtファイルを取得して表示します。画面全体を再読み込みすることなくページの内容が変化するというのがAjaxの特徴です図1⁠。

図1 Ajaxの概念図
図1 Ajaxの概念図

Ajax以前の脆弱性

リスト1で呼び出したのはcontents.txtという静的なファイル(毎回同じ内容のファイル)でしたが、実際にAjaxを多用したサイトを作成する場合には、呼び出すファイルの内容も動的に変化させたくなるでしょう。そもそも毎回同じ内容のファイルだったら毎回Ajaxで読み込む必要がありませんからね。

さて、動的に変化する内容にする場合には、呼び出す対象はcontents.txtではなくcontents.cgiとなります。
これにより、リスト1のリクエスト部分は以下のように変わります。


    req.open('GET', 'http://www.example.com/contents.cgi?str=Good+Morning+AJAX');

ここで、もしcontents.cgiに不正なスクリプトが含まれていた場合は何が起こるでしょうか?
ユーザのブラウザに不正なスクリプトが送り込まれ、実行されてしまいます。

これがクロスサイトスクリプティングという攻撃です。クロスサイトスクリプティングについては何年も前から指摘されており解説しているサイトも多数存在するため、一般的なクロスサイトスクリプティングの解説については他サイトに譲ることにします。

脆弱性の原因

クロスサイトスクリプティングが発生した原因を考えてみましょう。
Ajaxから呼び出されるファイルであるcontents.cgiに、不正なスクリプトを仕込まれてしまったことが原因です。

つまり、contents.cgiでクロスサイトスクリプティング対策が行われていなかったということになります。このように不正なスクリプトを入力されたとしても、それをそのまま出力しないでエスケープ処理を行ってから出力することが、クロスサイトスクリプティング対策になります。

いろいろなファイル形式

今回の例では読み込むファイルとしてTextやHTMLを挙げましたが、他にどのような形式があるでしょうか? どのような形式を使用しなければならないという決まりはないので、開発者が使いやすいものを使うことができます。通常は以下の形式がよく使われています。

  • HTML
  • Text
  • XML
  • CSV
  • CGI(HTML)
  • JSON
※JSON(JavaScript Object Notation)についてはこの連載の第3回で紹介する予定です。

さて、ここで注意しなければならないのが、これらのファイルを動的に生成する場合です。本来これらのファイルはAjax経由で呼び出されるものですが、直接これらのファイルにアクセスすることもできます。このとき、不正なスクリプトを混入されてしまっていた場合には、クロスサイトスクリプティングが発生することになります。

もう少し詳しくクロスサイトスクリプティングが発生する状況を見ていきましょう。たとえばCSVファイルの場合ですと、単にカンマで区切られたデータですので、スクリプトは実行されないはずです。しかし、Internet Explorerの仕様に「内容によってファイルを開く」というのがあります図2⁠。

図2 IEの「拡張子ではなく、内容によってファイルを開く」設定
図2 IEの「拡張子ではなく、内容によってファイルを開く」設定

これは、Internet Explorerがファイルの中身を見て、その中にHTMLっぽい文字列が含まれていればHTMLだと判断するということを意味しています。このため拡張子やレスポンスに含まれるContent-Typeヘッダとは関係なく、外部から参照可能なファイルにはクロスサイトスクリプティング対策が必要であるということになります。

一方、Firefoxの場合はレスポンスのContent-Typeヘッダを見て判断しますので、ファイルの中身が何っぽいのかを気にする必要はありません。

このように、Ajax経由でアクセスさせることを想定しているファイルであっても、ブラウザで直接アクセスされた場合のことも想定しておく必要があります。

図3 ファイルへ直接アクセス
図3 ファイルへ直接アクセス

Ajaxに潜む脆弱性

すべてのファイルでクロスサイトスクリプティング対策を行う必要があると書きましたが、これはAjaxだからというわけではなく、(Web1.0の時代)から言われている話です。また、クロスサイトスクリプティングに限らず、その他の脆弱性についても同様のことが言えます。その他の脆弱性で発生しやすいものとして、次のものがあります。

  • SQLインジェクション
  • OSコマンドインジェクション
  • セッションハイジャック
  • CSRF(Cross Site Request Forgery)

どれもAjaxに限ったものではありませんので、それぞれの脆弱性の説明は省略することにします。

それではAjaxを利用したサイトの特徴を考えてみます。
Ajaxを使用したサイトでは、非同期で通信できるという利点を生かして非常に多くのページを読み込みます。ユーザのマウスジェスチャーのたびにも多くのページが読み込まれます。1ページ開いているだけでも、ユーザの気づかないところで数十リクエストが発生しているのです。たとえば、Ajaxを駆使したサイトとして有名なGmailでは、ログインするだけで20リクエストが発生していました。

このようなすべてのリクエストに対してクロスサイトスクリプティング対策を行う必要があります。
Ajaxを使用していないサイトでは、10ページあれば10ページに対策を行えばよかったのですが、Ajaxを使用しているサイトでは10ページ×10ほどのページに対策を行うことになります。

図4 攻撃面の増加
図4 攻撃面の増加

このように対策を行わなければならない箇所が爆発的に増えたことが、Ajaxのセキュリティ対策を難しくしている理由のひとつです。

おすすめ記事

記事・ニュース一覧