ファイアウォール越しの信頼できないスクリプトからのリソースの保護
by
Ray Whitmer and Harish Dhurvasula
はじめに
このページでは、サンドボックス内のスクリプトからの要求に対して全ての内部リソースを保護するのに使用される代替的な機構について説明します。
これは特に、信頼できないスクリプトによる SOAP 呼び出し用に実装されたものです。
予め知らされていない URI のリソースへのアクセス要求があった場合、
サンドボックスは、そのスクリプトがアクセス許可を持っているかどうかを判定するために、そのドメインに置いてある宣言ファイルを読みにいきます。
もしそのファイルが無い場合、アクセスは拒否されます。
問題
ファイアウォール越しにロードされた外部の信頼できないスクリプトは、サンドボックス内で実行されます。
これらのスクリプトは、正当に外部リソースへのアクセスを要求できます。
しかし、内部リソースへのアクセス許可を与えることは、通常はファイアウォールの外のアプリケーションが利用できないようなこれら内部リソースに対する不正利用を許すことになってしまいます。
サンドボックスにおいては、内部リソースを区別し、保護しなければなりません。
クライアント側の制御による解決策
ファイアウォール越しにロードされたサンドボックス内のアプリケーションと、ファイアウォール内で保護されている他のリソースとが、やり取りできないようにするために設計された、クライアント側の制御による解決策がいくつか存在します。
同一ソース制限
サンドボックス内のスクリプトがアクセスできるリソースをそのスクリプトのロード元のドメイン内にあるリソースのみに制限することにより、あるドメインから別のドメインにロードされた全てのスクリプトにおいて、そのスクリプトがロード先のドメイン内のリソースにアクセスできなくなるようにします。
この方針は、Web 上の JavaScript および Java アプレットのサンドボックス化においても広く成功しているものです。
もしも、サンドボックスにおいて、信頼できないドメインの URI と信頼しうるドメインの URI の共通部分とに相違がなかった場合には、その同一のドメインからロードされたスクリプトはファイアウォールに保護されているリソースを利用できるようになります。
さらに、この手法により、スクリプトは、そのスクリプトと同一のドメイン内で提供されていない多くの正当な外部リソースにアクセスできなくなります。
このことは、スクリプトからは、自らのドメインで公開されている以外の Web サービスやデータにアクセスできなくなることを意味します。
ホワイトリスト
信頼できる URI のホワイトリストを作成し、そこから来たスクリプトを信頼して内部リソースを危険にさらさないようにするという方法もあります。
これにより、厳しい同一ソース制限のサンドボックス内からドメインを解放することができるようになります。
ホワイトリストは、常に信頼できるドメインを含むのには良いツールになります。
しかし、Web 上では、内部ドメインを危険にさらさずに、他の信頼できないドメインへのアクセスを許可する必要があるのは、たいていの場合はあまり信頼できないドメインからのスクリプトです。
どのドメインへアクセス可能で、他のどのドメインから許可されているかといったような、もっと粒度の細かい複雑なアクセスリストを作成することも可能かもしれません。
しかし、これには大規模な管理が必要になります。
つまり、良くてもエンドユーザの間違いの元、さらには簡単にファイアウォールに穴を開けることにもなります。
これにより、外部のサービスにアクセスしようとしてブラウザを設定し直したユーザが直接被害を受けることはないかもしれませんが、そのファイアウォール内の他のサービスの提供者が被害を受ける可能性があります。
署名付きスクリプト
スクリプトの作者がスクリプトに電子的な署名を行うことにより、ある程度の追加の信頼を与える助けになる場合もあるでしょう。
しかし、署名付きのスクリプトは現実には定着してはいません。
なぜなら、署名付きスクリプトには証明書が必要ですが、このことによって、完全に見知らぬ相手が内部リソースにアクセスしようとするスクリプトを書いていたという根本的な問題は何も変わらないからです。
ユーザへの確認
サンドボックス上において、実行しているスクリプトが当該リソースへのアクセスを許可されているかどうかを他の方法で判定できなかった場合には、ユーザに特別に権限を許可するかどうか尋ねるダイアログが出る場合もあります。
これは現在、ローカルに保存されているスクリプトと署名付きスクリプトに許されています。
また、上記で述べたホワイトリストや署名付きスクリプトなどといった他のオプションとの組み合わせになることもありえます。
しかし、この方式の大きな問題は、会社のファイアウォールにうっかり穴を開けることになるかもしれないという影響について、典型的なブラウザ利用者は理解していなかったり、気付かなかったりするという点にあります。
ユーザが他のリソースを危険にさらすことなく、希望の外部のサービスへのアクセスを許可できるようにするためには、非常に複雑な設定が必要になることでしょう。
サーバ上でのリソースへのアクセス制御
あるリソースをファイアウォールの外側からロードした Web アプリケーションから隔離すべきかどうかを決定するために、信頼できないスクリプトによるアクセスを、(ユーザという立場ではなく)リソースとサーバ双方の所有者であるような直接の関係者の制御下に置く必要があります。
SOAP ヘッダによる検証
SOAP メッセージには、特定のヘッダを受け取り手が理解し対応しなければならないという独特の処理モデルがあります。
これにより、あるスクリプトが信頼できない場所からのリクエストであるということを識別できます。
信頼できないスクリプトによるアクセスをそのまま通過できなかった SOAP サービスは、そのリクエストを拒否します。
この機能は、現在の Mozilla の SOAP 実装で提供されています。
残念ながら、この機能により SOAP メッセージが非 SOAP アドレスに送られなくなるという訳ではありません。
このこと自体も十分に大きな問題になります。
つまり、この検証機能では、
信頼できないリクエストがファイアウォールにより保護されるべきサービスによって常に適切に拒否される、という保証がされないことになります。
SOAP サービスが特定の検証ヘッダを無視するように変更することは、トラブルの元にもなるかもしれません。
宣言ファイルの使用
もっと確実な解決策は、web-scripts-access.xml という名前のファイルの取得に頼る方法です。
このファイルを、サンドボックス内のスクリプトがリクエストするサーバのルートディレクトリに置きます。
この手法は、公開リソースを作成しているたいていの提供者にとって、かなり容易な選択肢となるでしょう。
Web スクリプト・アクセスの記述
アクセスファイルの文法は以下の通りです。
<!ELEMENT webScriptAccess (delegate?|allow*)>
<!ELEMENT delegate EMPTY>
<!ELEMENT allow EMPTY>
<!ATTLIST allow type|from CDATA #IMPLIED>.
ルート要素
ファイルの最初の要素は以下のようになります。
<wsa:webScriptAccess
xmlns:wsa="http://www.mozilla.org/2002/soap/security">
委譲
もし <delegate/> 要素が存在する場合は、その URI に対応するサブディレクトリに "web-scripts-access.xml" が必要になります。
例えば、問題になっているスクリプトが http://www.example.com/foo/bar.xml にあって、宣言ファイル http://www.example.com/web-scripts-access.xml に "delegate" キーワードが含まれる場合、http://www.example.com/foo/web-scripts-access.xml へその権限を委譲します。
もしも URI がサブディレクトリにあって、ルートディレクトリのアクセスファイルが委譲しているのにサブディレクトリにアクセスファイルが無い場合には、アクセスは許されません。
また、ルートのアクセスファイルが委譲していない場合には、そのアクセスファイルがサブディレクトリに渡って全てのリソースを扱うことになります。
アクセスファイルになんらかの文法エラーがある場合は、ファイルの残りの部分も無視されることになります。
コマンドはアクセスを許可することだけができるため、パースした "allow" コマンドの処理順序は重要ではありません。
Web スクリプトのアクセスを有効にする
スクリプトがこのサーバのリソースにアクセスできる許可を与えるには、次のコマンドを使います。
<wsa:allow type="<request-type>" from="<uri-prefix>"/>
リクエストタイプが指定されている場合、スクリプトによるリクエストのタイプをチェックします。
"soap" や "soapv" や "load" などが指定できます。
リクエストタイプにスペースを含むことはできません。
リクエストタイプに "any" が指定されると、リソースへの全ての種類のアクセスが許可されます。
スクリプトの URI は、指定した URI プレフィックスに対してチェックされます。
"from" が指定されていない場合、全てのスクリプトが許可されます。
注意: "from" の値としてワイルドカードを使うことも可能です。
例えば、
<wsa:allow type="soapv" from="http://www.mozilla.org"/>
このコマンドは、www.mozilla.org ドメインからロードされたスクリプトからの検証ヘッダ付きの SOAP リクエストを許可します。
<wsa:allow type="soapv" from="http://*.mozilla.org"/>
このコマンドは、mozilla.org を含むホスト名を持つドメインからロードされたスクリプトからの検証ヘッダ付きの SOAP リクエストを許可します。
つまり、http://www.mozilla.org/, http://lxr.mozilla.org/, http://komodo.mozilla.org/ などからのアクセスが許可されます。
実装
nsIWebScriptsAccessService
このインタフェースは実行中のスクリプトが通信したいサーバへアクセスできるかどうかをチェックする機能を提供します。
- boolean canAccess(in nsIURI aTransportURI, in AString aType);
- aTransportURI -- サービス URI
- aType -- スクリプトによってリクエストされるタイプ(例: soapv, soap, load など)
- アクセスが許可されたら PR_TRUE を返し、許可されない場合は PR_FALSE を返す
- void invalidateCache(in string aTransportURI);
- 与えられたサービス URI に対するキャッシュエントリを無効にする
- 空文字列を渡すことによりキャッシュを空にできます
nsWebScriptsAccess
( Implements
nsIWebScriptsAccessService)
サーバに対するアクセス情報をアクセス情報キャッシュ(ハッシュテーブル)として管理します。
エントリがキャッシュ内に見つからない場合、宣言ファイル(web-scripts-access.xml)をロードして、その情報を取り出してキャッシュを生成します。
まず、アクセスを判定するために、リクエストタイプとプレフィックスを許可されているタイプとプレフィックスと比較します。
宣言ファイルが妥当(上記で述べた文法に基づき検証)だった場合に限り、エントリが作成されます。
妥当でない文書だった場合には、アクセスは拒否されることになります。
XML の整形式エラー、妥当性検証エラー、または、宣言ファイルがアクセスを許していない場合には、スクリプトのアクセスを拒否します。
nsIConsoleService を通じてコンソールにエラー(検証、整形式、ファイルが見つからない、など)を報告します。
注意:
スクリプト・セキュリティ・マネージャがアクセスを拒否した場合に限り、宣言ファイルを通じたスクリプトアクセスのチェックが行われます。
まとめ
利点
ここで提案した宣言ファイルの手法は、信頼できないスクリプトによるサーバへのアクセス制御をクライアント側ではなくサーバ側で行うものです。
この手法によるアクセスの穴は、サービスにすでにある穴より大きくはなりません。
アクセスはデフォルトでは無効になっており、ユーザが必要としない限りアクセスをオープンにする必要はなく、間違ってユーザ側のファイルウォールに穴を開けてしまうことも無いでしょう。
アクセスを許可するためのアクセス宣言ファイルを Web サーバのルートディレクトリに置くというのは、非常に容易なことでしょう。
混合所有に伴う委譲
ルートディレクトリの所有者が委譲宣言を行ったアクセスファイルをルートディレクトリに置かない限り、サブディレクトリ毎の所有者が個別にそのサブディレクトリへの Web スクリプトのアクセスを許可することはできません。
通常は、サーバがファイルウォールの外側か内側のどちらにあるかは自明のことでしょうから、このことはさほど問題にはならないでしょう。
サーバの所有者が複数に渡る場合に、Web スクリプトのアクセスファイルを探して全てのディレクトリをスキャンするなどという別の方法を取るのは、望ましくないものと思われます。
その一方で、トップの所有者が Web サービスへのアクセスを提供している場所についてさほど考慮していないようなドメインでも、独立した運用が可能なこの手法は、おそらくそんなに悪い選択肢ではないと思います。
調整
この新しいモデルが SOAP さらに document.load や xml-request にも適用されるようになるにつれて、同一ソースのセキュリティ制限を回避する手法は廃止した方が良いようになっていくかもしれません。
なぜなら、その手法が常に安全であることは明らかでないからです。
また、他のセキュリティ上の調整も同様に必要になるかもしれません。
フィードバック
本提案についてのご意見などありましたら、私の方までお送りください。