前編では、クロスサイトスクリプティング(XSS)攻撃の基礎知識として、XSS攻撃が成立する仕組みについて説明した。今回はXSS攻撃を防ぐための手法を紹介する。
自社のサイトがXSS攻撃の被害に遭う確率を下げるためには、何らかの形のセキュリティ開発ライフサイクル(SDL)を使ってWebアプリケーションを開発することが不可欠だ。その目的は、アプリケーションの設計とコーディング段階でセキュリティ関連問題の数を減らし、問題が見つけられずに残ってしまった場合でも危険性を抑えることにある。セキュアなアプリケーションの開発において学ぶべき鉄則として、そのアプリケーションが受け取るデータはすべて、信頼できないソースから来ることを前提としなければならない。これは、そのアプリケーションで受け取るデータ、cookie、電子メール、ファイル、画像など、あらゆるデータに当てはまる。たとえ自分のアカウントにログインして認証を済ませたユーザーからのデータであっても同じだ。
ユーザーの入力データを信頼しないということは、データを信頼できる境界へと受け渡す都度、そのデータの種類、長さ、フォーマット、レンジをチェックするということだ。例えば、Webフォームからアプリケーションスクリプトに変換し、その後エンコードしてから動的ページへ再表示するような場合がこれに当たる。実際の環境では、自社のサイトでユーザー提供のデータが処理されるすべてのポイントを見直し、ユーザーに再提示する前にクライアントサイドから受け取った値をすべて確実にチェックし、フィルタにかけ、エンコードすることになる。

クライアントサイドのチェックは当てにはならないが、ユーザーの入力したデータをWebアプリケーションで利用する前に、サーバサイドの処理で強制的に最小限の英数字セットにすることはできる。正規表現を使って検索と置換を行えば、ユーザーの入力したデータに悪質な意図がないことを確認できる。このクリーニングと検証の作業は、別のプロセスに受け渡す前に、すべてのデータについて実行しなければならない。例えば、電話番号の欄ではカッコと長音記号以外の句読点などは一切受け付けてはならない。「<」「>」などの特殊記号をユーザーが入力してきた場合は、再表示する前にエンコードする必要がある。例えばスクリプトタグをエンコードすれば、ブラウザで<script>と表示されるが実行はされなくなる。エンコードと併せて、Webページでは必ず文字コードを指定し、ブラウザが別の文字セットの特殊記号エンコーディングを解釈してしまわないようにする。
ブラウザではそのページの文字コードのデフォルトの値が必ずしも認識されず、サーバによっては文字コードのパラメータを送ることを認めていない、あるいは認める設定になっていないことを考えると、Webページにこのメタタグを欠かすことはできない。これによって、スクリプトを挿入される可能性が大幅に減るからだ。もしも自社のWebアプリケーションでISO-8859-1の文字コード以外の文字を表示する必要がないのなら(英語など欧州言語の場合はこれで十分足りる)、全ページに次のメタタグを入れて文字コードを指定しておくといい。
<META http-equiv="Content-Type" content="text/html; charset= ISO-8859-1">
リッチデータを受け入れる必要のないWebアプリケーションは、エスケーピングを使えばXSSのリスクを完全に排除できる。もちろん、アプリケーションで「<」「>」などのHTML記号を受け入れなければならないときもある。例えば、フォントのフォーマット指定を機能として取り入れているソーシャルネットワーキングサービス(SNS)などだ。このような入力情報のセキュアなエンコーディングは、HTMLの柔軟性と複雑性故に難しくなる。
そこで、わたしはセキュリティエンコーディングライブラリの利用を勧めている。MicrosoftのASP.NETでは、ユーザーの入力情報をチェックできる認証サーバコントロールを提供している。Apacheサーバで実行しているWebアプリケーションやPerlプログラミング言語を使っているWebアプリケーションなら、「Apache::TaintRequest」モジュールや「PerlTaintcheck」を使って外部データ処理のプロセスを自動化できる。こうした追加的な安全措置をコードに取り入れる方法は、自社の開発者全員に理解を徹底する必要がある。
XSS攻撃に対するもう1つのガードとして、認証を受けたユーザーが特定のサービスにアクセスするためにもう一度パスワードを入力しなければならない「境界クロッシング」がある。例えば、ユーザーがcookieで自動的にサイトにログインしたとしても、重要なアカウント情報にアクセスするためには再度ユーザーネームとパスワードを入力しなければならない。こうして境界を増やすことにより、XSS攻撃によってセッションが乗っ取られる可能性を抑えられる。もう1つ、単純だが効果的なのは、複数のマシンがそれぞれ異なる2つのIPアドレスから同じセッションデータを利用しようとしてきた場合、直ちにセッションを終了させる技術だ。セッションIDは、タイムスタンプやIPアドレスなど各ユーザー特有の情報を使って作成できる。この技術はIP詐称によってかわすことが可能だが、自動化された攻撃に対するセキュリティの層を厚くする効果はある。
アプリケーションの開発中には、自動ソースコードスキャンツールとWeb脆弱性スキャナの利用を検討するといい。優れたWeb脆弱性スキャナは、XSSの脆弱性などよくある技術的な弱点を見つけてくれる。自社のサイト上で検索エンジンなどのサードパーティーパッケージを利用する場合、既知の脆弱性や設定上の問題について、必ずベンダーに確認することが必要だ。その後、不正な入力がどう処理されるかを徹底検証する。セキュアだという前提に立ってはならない。
Webアプリケーションを実際に導入する前には侵入テストを実施する必要がある。攻撃のシミュレーションによって、システム設定の不備、ハードウェアやソフトウェアの脆弱性、そのサイトを守っている周辺防御の弱さなどに起因する潜在的なXSSの脆弱性がサイトに残っていないかどうかを判断できる。ISECOMの「Open Source Security Testing Methodology Manual(OSSTMM)」では、セキュリティ検査の実施と結果判定について定評のある方法論を提示しているので、一読をお勧めする。
現在ではほとんどのサイトが、クライアントサイドスクリプトなしには機能しない。従って、ブラウザでスクリプトを無効にするようユーザーに求めるのは、実質的な解決にはならない。何よりも、ほとんどのユーザーはどのみちそのやり方を知らないのだ。XSSに対抗する取り組みとして、MicrosoftがInternet Explorer(IE) 8にXSSフィルタを実装したのは評価できる。この目的は、一般的なXSS攻撃をサーバのレスポンスで再現しようとすると自動的に検出して防止する機能の提供にある。ユーザーに答えられないような質問を提示するのではなく、IEが単純に悪質なスクリプトの実行を阻止してくれる。
しかし行き着くところ、セキュア開発ライフサイクルに従うのはWeb開発者の責任であり、サイトの脆弱性をスキャンしてWebアプリケーションファイアウォールでサイトを守るのはWeb管理者の責任だ。XSSで最終的に傷つくのは顧客と自社の評判なのだ。
本稿筆者のマイケル・コッブ氏は、データセキュリティ・分析関連のトレーニングやサポートを提供するITコンサルティング会社Cobweb Applicationsの創業者、マネージングディレクター。CISSP-ISSAP(公認情報システムセキュリティプロフェッショナル―情報システムセキュリティアーキテクチャプロフェッショナル)の資格を持つ。共著書に「IIS Security」があり、大手IT出版物に多数の技術記事を寄稿している。