アクセシビリティ
デベロッパーリソース

Flash Player 記事

 

ソケットポリシーファイルサーバの設定


Peleus Uhley

Peleus Uhley

Adobe

作成日:
2008年4月14日
ユーザレベル:
中級
製品:
Flash
Flash Player
Flex

先頃登場したAdobe Flash Player 9,0,124,0から、Flash Playerはあらかじめサーバから明確な許可を得ることなく、当該サーバに対してダイレクトなソケット接続を生成できなくなりました。 これにより、一部のシステムおよびネットワークでは、許可の付与を可能にするために新たなポートを開いたり、新たなサービスを提供する必要が発生します。

今回変更されたFlash Playerの動作は、システム管理者およびネットワーク管理者に新たな課題を投げかけることになりかねません。そこでこの記事では、このような動作がなぜ必要であるかの背景を紹介するとともに、ネットワークにどのような影響を与えるかについて解説します。また本記事には、ソケットポリシーファイルサーバを動作検証環境で構築する際に利用できる、アドビ提供のサンプルコードの解説も含まれています。

必要条件

本記事の内容の理解を深めるには、次のソフトウェアおよびファイルが必要です。

Flash Player 9 Update 3(9,0,124,0)またはそれ以降

サンプルスクリプト:

メモ: このコードは本稼働向けのコード品質を有するものではなく、セキュアな環境での動作検証を経ていません。あくまで、ソケットポリシーファイルサーバの基礎概念を示すことを目的に提供されているものです。アドビでは、このコードを公式にサポートする予定はありません。

この記事に必要な予備知識

ネットワークソケットおよびオペレーティングシステムサービスに対する理解・知識が必要です。 ActionScript 2.0またはActionScript 3.0の知識も推奨されますが、必須ではありません。

Flash Playerのソケット機能とソケットポリシーファイル

本記事はWebチームからファイアウォールの一部のポートの解放依頼、または新規システムサービスの実装依頼を受けたシステム管理者またはネットワーク管理者を対象読者として想定したものです。一見このような要求は、より閉鎖的にすることでより安全性を高めるという、セキュリティ原則に反するように感じられるかもしれません。そこで本節ではソケットポリシーファイルについて簡単にその背景を紹介するとともに、ネットワークにどのような影響を与えるかについても解説します。また、ソケットポリシーファイルサーバがFlash Playerランタイムに対して何を提供しなければならないかについても、その枠組みを説明します。

ソケットポリシーファイルが必要な理由

Flash PlayerコンテンツはWeb上で幅広く配布され、ダイレクトコンテンツプロバイダや広告提供者によってホスティングされています。Flash Playerコンテンツが広く普及しているのは、Flash Playerには「生」のHTMLよりリッチなデジタル体験を実現するための機能が数多く含まれているからです。その一例として挙げられるのが、サーバとのデータ通信用にTCPソケット接続が作成できるという機能です。ネットワーク管理者の立場からすれば、インターネット上で取得されたコンテンツから内部ホストへのソケット接続が作成できるということは、逃げ腰になりかねない概念です。だからこそ、Flash Playerではコンテンツにネットワーク接続の作成を許す前に、当該ターゲットホストからの許可が必要とされます。

ソケットポリシーファイルに関する今回の変更点

Flash Playerでは、ソケット機能の搭載当初からソケットポリシーファイルの存在が必要とされていました。Flash Player 9,0,124,0には、このソケットポリシーファイルに関する2つの主な変更が含まれています。1つ目は、今後、Flash Playerがあらゆるソケット接続において、必ずソケットポリシーファイルを必要とすることです。従来のFlash Playerバージョンでは、SWFファイルが自らのホスティング元であるサーバに接続する場合に限り、1024より上のポートにそのまま接続することができました。2つ目の変更点は、ソケットポリシーファイルの中央化を可能にする一元的な位置が新たに制定されたことです。これにより、ソケットマスターポリシーファイルが設置できるようになります。

アドビでは、ソケットポリシーファイル配信用としてポート843をリザーブするよう、既にIANA(Internet Assigned Numbers Authority*)への申請手続きを済ませています。ソケットポリシーファイル用の一元的な位置が制定されることにより、システム管理者は、ホスト上の他のポリシーファイルの設定をオーバーライドする、単一のマスターポリシーを通じて、どのポートが利用できるかを指定できるようになります。仮にFlash Player 9,0,124,0がポート843からマスターポリシーファイルを取得できない場合は、接続しようとしているポートに対してソケットポリシーファイルのリクエストが行われます。ただし、ポリシーファイルがTCPポート843上のサービスを介して公開されている場合は、Flash Playerは、これを当該システムの全権的な許可群として扱います。

ソケットポリシーファイルを利用して管理者が制御できる事柄

ソケットポリシーファイルでは、どのホストがシステムに接続できるかと、これらのホストにどのポートでの接続を許可するかを規定できます。ソケットマスターポリシーファイルの場合は、当該ホスト上で他のソケットポリシーファイルを許可するかも、あわせて定義できます。ソケットポリシーファイルのスキーマは、adobe.com/xml/schemas/PolicyFileSocket.xsdに定義されている通りです。次にソケットマスターポリシーファイルの例を示します。

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">
<!-- Policy file for xmlsocket://socks.example.com -->
<cross-domain-policy>
   <!-- This is a master-policy file -->
   <site-control permitted-cross-domain-policies="master-only"/>
   <!-- Instead of setting to-ports="*",
administrators can use ranges and commas -->
   <!-- This will allow access to ports 123, 456, 457, and 458 -->
   <allow-access-from domain="swf.example.com" to-ports="123,456-458" />
</cross-domain-policy>         

cross-domain-policyノードにはsite-control要素が含まれています。このsite-control要素には、サーバ上で、どのソケットポリシーファイルを許可するのかを定義します。上記の例の場合、値には"master-only"が指定されており、当該サーバ上では、このポリシーファイルのみがFlash Playerによって認知されるべきものであることが規定されています。他のポートに対するソケットポリシーファイルの定義を許可したい場面では、"all"が指定できます。一方、当該システムへのすべてのソケット接続を拒否したい場合は、値に"none"を指定します。Flash Playerがソケットマスターポリシーを取得できなかった場合、あるいはソケットマスターポリシーにsite-control要素が含まれていない場合、Flash Playerはデフォルトの設定として"all"を適用します。

XMLの次の行にあるのはallow-access-from要素です。この要素の最初のフィールドでは、接続を許可するドメインを定義します。ここには、SWFコンテンツがホスティングされているドメインと同じものを指定するようにします。なお、ここで指定するドメインは、SWFコンテンツを参照するHTMLページがホスティングされたドメインとは異なる場合があります。たとえば、仮にHTMLページが www.example.com にホスティングされ、このページが swf.example.comでホスティングされたSWFを参照するようなケースでは、 swf.example.comdomainフィールドで指定します。domainフィールドにおいてワイルドカード(「*」または「*.example.com」など)を使用することも可能ではありますが、アドビでは、明示的なドメイン名のみを指定することを推奨しています。

allow-access-from要素のto-portsフィールドには、swf.example.comでホスティングされたFlashコンテンツに対して、どのポートが用意されているかを指定します。このフィールドには、ワイルドカード(「*」)、ポートの範囲、および(または)個別のポートを指定することができます。アドビでは、当該ドメインからのアクセスを許可するポートのみ、明示的に指定することを推奨しています。

ソケットポリシーのリクエストプロセス

Flash Playerは、ソケットポリシーファイルを探すために各IP接続につき3カ所をチェックします。このチェック作業は以下の順に行われます。

  1. Flash Playerは、まずソケットマスターポリシーファイルの有無についてポート843をチェックします。ソケットマスターポリシーファイルが見つからない場合、あるいはソケットマスターポリシーファイルがあるものの、このポリシーのsite-controlタグで"all"が指定されている場合、Flash Playerは次の手順へと進みます。site-controlタグの値が"none"の場合はプロセスが終了し、当該ソケットによる接続が拒否されます。
  2. 当該SWFファイル上にActionScriptのSecurity.loadPolicyFile()コマンドが存在する場合、Flash Playerランタイムはそれに指定された場所をチェックします。この際、Flash Playerは他のポリシーファイルを参照することが許可されているかについて、ポート843のマスターポリシーファイルをチェックしてから、loadPolicyFile()に指定された場所をチェックします。当該コンテンツのデベロッパーがloadPolicyFile()コマンドを規定していない場合、Flash Playerは接続先のポートをチェックします。
  3. 接続先のポートは、Flash Playerがチェックする最後の場所です。このチェックは、ソケットマスターポリシーファイルによって、Flash Playerが他の場所をチェックすることが許可されている場合に限り行われます。Flash Playerが、ここでも許可を付与するポリシーファイルを見つけられなかった場合、ソケット接続は拒否されます。

リクエストおよびレスポンスで送信されるデータ

ポリシーファイルのリクエスト自体は非常に簡単なものです。Flash Playerは、文字列の<policy-file-request/>と、それに続くNULLバイトをポリシーファイルのリクエスト先ポートに送ります。Flashデベロッパーが、送信される文字列に手を加えることはできません。リクエストに対するFlash Playerへのレスポンスとしては、テキスト形式のソケットポリシーファイルが返されます。Flash Playerがソケットポリシーファイルを受信すると当該接続が閉じられ、そして、このポリシーファイルにリクエストの許可が含まれている場合は新たな接続が別途確立されます。

Flash Playerが接続を作成する頻度

一旦許可を得るとFlash Playerは当該SWFファイルの生存期間中、その結果を記憶し続けます。Flash Playerは各ソケットポリシーファイルを特定のIPアドレスに関連付けるとともに、新たなIPアドレスへの接続ごとにポリシーファイルを必要とします。たとえば、デベロッパーが接続のホスト名を指定し、これに対するDNSルックアップが複数のIPアドレスを返すような場合、当該ホスト名に対応するIPアドレスが変わるたびに、Flash Playerはソケットポリシーファイルを探すために新たなIPアドレスをチェックします。この動作は、DNS再バインディング攻撃からの保護に役立ちます。

また、Flash Playerは、デベロッパーによってコード内にSecurity.loadPolicyFile()コマンドが規定されているたびに、その都度ポリシーファイルをチェックします。ブラウザを介した通常のHTTP接続またはHTTPS接続に関しては、Flash Playerはソケットポリシーファイルをチェックしません。ソケットポリシーファイルが用いられるのは、ActionScriptによって実際のSocket接続またはXMLSocket接続が確立されようとする場面のみです。

ソケットポリシーファイルサーバのサンプル

アドビでは、デベロッパーによる動作検証用として、ソケットポリシーファイルサーバのサンプルを用意しています。このコードは本稼働向けのコード品質を有するものではなく、セキュアな環境での動作検証は経たものではありません。このコードはソケットポリシーファイルサーバの基本概念を示すためのものです。アドビがこのコードを正式にサポートする予定はありません。また、ここで紹介するスクリプトをご利用中のオペレーティングシステム上の1サービスとして実行するには、一部の構成を変更または追加しなければならないことがあります。

サンプルの概要

サンプルコードはPerlとPythonで用意されていますが、ソケットをサポートする言語であればどれを使用しても、ソケットポリシーファイルサーバを記述することができます。この2つの言語が選ばれているのは、あくまでコードの読みやすさとクロスプラットフォーム対応性を考慮したことと、わずか数行のコードで概念を紹介できるからに過ぎません。サンプルにはPython、Perlの両バージョンのスタンドアローンスクリプトに加えて、xinetdサービス用のPythonおよびPerlサーバ、initサービス用のPythonバージョンのサーバが含まれています。これらのファイルをすべてインストールする必要はありません。異なるバージョンが用意されているのは、さまざまな環境向けとして選択肢を提供するために過ぎません。なお、サーバの完全な機能性を確保するには、ご利用の環境に応じて、( /etc/services ファイル内のファイルに"flashpolicy"サービス用としてTCPポート843のエントリを追加する、ファイアウォールの設定でポート843の使用を許可する、SELinuxの構成設定で所定の権限を追加するなど)他にも手動での追加作業が発生することがあります。なおPythonスクリプトを使用するにはPythonバージョン2.5が必要です。

スタンドアローンスクリプト

サンプルファイルのStandaloneフォルダには、PerlとPython両方のスタンドアローンソケットポリシーファイルサーバスクリプトが収録されています。これらのスクリプトはユーザがCtrl+Cキーを押すか、ウィンドウを閉じてプロセスを停止するまで、単にループを実行するものです。また、これらのスクリプトはWindowsではCygwin上で実行できるだけでなく、他にも、ActiveStateが配布するPerlおよびPythonを利用してWindows上でネイティブに実行できるはずです。flashpolicyd.plスクリプトとflashpolicyd.pyスクリプトは、いずれも2つの引数を受け付けます。1つ目の引数は、ファイルシステム上のソケットポリシーファイルへのパス指定。そして、2つ目の引数は、サーバがリッスンするTCPポートを指定するためのオプション項目です。ポートを明示的に指定しない場合、これらのスクリプトはTCPポート843をリッスンします。スクリプトを開始するためのコマンドライン入力例は以下の通りです。

./flashpolicyd.pl --file=../policyfile.xml --port=843
./flashpolicyd.py --file=../policyfile.xml --port=843

Perlスクリプトは基本的なデバッグ情報のログをSTDOUTに記録します。これによりデベロッパーは、いつリクエストが受け取られたか、リクエストが有効であると判定されたか、レスポンスとしてポリシーファイルが送られたか、といった事柄を把握することができます。エラーのログはSTDERRに記録されます。Pythonスクリプトも同様の情報を追跡はするものの、出力はすべてSTDERRに行われます。

xinetdサービス

Perl用、Python用のいずれのスクリプト群も、ソケットポリシーサーバをxinetdが実装されたLinuxマシンで実行するために用意されています。インストールする必要があるのは、2つのスクリプト群のうち片方のみです。 install.shスクリプトの実行には、当該マシンのルート権限が必要です。 このスクリプトは以下のファイルをコピーします。

  • ソケットポリシーファイル(flashpolicy.xml) > /usr/local/etc/
  • ポリシーサーバスクリプト > /usr/local/sbin (in.flashpolicydファイルとしてコピー)
  • Xinetdコントロールファイル > /etc/xinetd.d/

コピー処理後、install.shスクリプトは当該サービスの起動を試みます。このxinetdサービスはユーザ「nobody」で実行されます。Python版のポリシーファイルサーバはsyslogに、Perl版はSTDERRにそれぞれログを記録します。これらのスクリプトはinetdやlaunchconfigdといった他のスーパーサーバでも実行できますが、これらのシステム用の設定&インストーラファイルは含まれていません。

Pythonデーモン

Python_initフォルダに配置されているPythonデーモンをインストールするには、当該Linuxマシンのルート権限が必要です。xinetdのスクリプト群同様に、install.shスクリプトはポリシーファイルサーバ用のPythonファイル(flashpolicyd.py)をflashpolicydとして /usr/local/sbin にコピーします。また、基礎的な「start」「stop」「restart」コマンドをサポートするinitスクリプトが、 /etc/rc.d/init.d/ へとコピーされます。install.shスクリプトは、flashpolicy.xmlファイルを /usr/local/etc/にもコピーします。そして最後に、当該サービスの起動が試みられるとともに、ブート時にこのサービスが自動的に起動されるよう、設定が調整されます。このデーモンはルートユーザとして実行され、ログはSTDERRに記録されます。

動作検証

サービスの動作検証は、PerlまたはPythonのいずれかとnetcatユーティリティの組み合わせで素早く実行できます。

python -c 'print "<policy-file-request/>%c" % 0' | nc 127.0.0.1 843
perl -e 'printf "<policy-file-request/>%c",0' | nc 127.0.0.1 843

上記のいずれかのコマンドを実行してソケットポリシーファイルが返される場合は、正しい動作が確保されています。

Flashデベロッパーがこの動作検証を行う際には、Flash Player 9,0,115,0以降が必要となります。ソケットマスターポリシーのサポート、およびソケット接続をデバッグするための新たなログ機能は、Flash Player 9,0,115,0から実装されています。なお、SWFのホスティング位置と同じドメインにソケット接続を作成し、このソケット接続が1024より上のポートに接続するような場合、Flash Player 9,0,115,0とFlash Player 9,0,124,0(およびそれ以降)を使用するのでは、処理結果に多少の違いがあることに気付くデベロッパーもおられることでしょう。これは、Flash Player 9,0,115,0が、廃止された旧式の動作と新しいフェーズII方式の動作の両方をサポートする、移行対応版リリースであるからです。つまり、ソケットマスターポリシーファイルがポート843で見つからなかった場合、Flash Player 9,0,115,0は、1024より上のポートに対して旧式の動作を適用しなければならないと判断します。一方、Flash Player 9,0,124,0からは、より厳格な新しいフェーズII方式の動作のみがサポートされており、すべてのソケット接続に対してポリシーファイルが必要とされます。この2つのバージョンの相違点およびログ記録機能の設定方法について詳しくは、別途記事のFlash Player 9におけるポリシーファイルの変更点:ソケットポリシーファイルの節を参照してください。

フォルダ構成

以下に、本記事付属のZIPファイルに収録されたファイル群の内訳を示します。

(ルートフォルダ)

  • flashpolicy.xml: インストーラスクリプトによって /usr/local/etc/ にコピーされるソケットマスターポリシーファイル。このファイルは、ご利用のサーバに適したポートおよびドメインが反映されるように編集する必要があります。
  • README.txt: このアプリケーションおよびプロジェクトに関する情報を収録したファイル。

Python_xinetdフォルダ

  • install.sh: このファイルによって、サービスとして登録するために必要なファイルが所定のディレクトリへとコピーされます。スクリプトに記述されているインストールディレクトリが、ご利用中のシステムに適していることを確認するようにしてください。
  • in.flashpolicyd.py: このスクリプトは、xinetdとあわせて使用するために、インストールスクリプトによって /usr/local/sbin ディレクトリへとコピーされます。このスクリプトはPythonで記述されたポリシーファイルサービスであり、ログはsyslogに記録されます。
  • flashpolicyd.xinet: このxinetdコントロールファイルによって、ポート843、ユーザ「nobody」として実行されるよう、in.flashpolicyd.pyデーモンがxinetdに登録されます。このファイルはインストーラスクリプトによって、 /etc/xinetd.d ディレクトリに /etc/xinetd.d/flashpolicyd としてインストールされます。

Perl_xinetdフォルダ

  • install.sh: このファイルによって、サービスとして登録するために必要なファイルが所定のディレクトリへとコピーされます。スクリプトに記述されているインストールディレクトリが、ご利用中のシステムに適していることを確認するようにしてください。
  • in.flashpolicyd.pl: このスクリプトは、xinetdとあわせて使用するために、インストールスクリプトによって /usr/local/sbin ディレクトリへとコピーされます。このスクリプトはPerlで記述されたポリシーファイルサービスであり、ログはSTDOUTとSTDERRに記録されます。
  • flashpolicyd.xinet: このxinetdコントロールファイルによって、ポート843、ユーザ「nobody」として実行されるよう、in.flashpolicyd.pyデーモンがxinetdに登録されます。このファイルはインストーラスクリプトによって、 /etc/xinetd.d ディレクトリに /etc/xinetd.d/flashpolicyd としてインストールされます。

Python_initフォルダ

  • install.sh: このファイルによって、サービスとして登録するために必要なファイルが所定のディレクトリへとコピーされます。スクリプトに記述されているインストールディレクトリが、ご利用中のシステムに適していることを確認するようにしてください。
  • flashpolicyd.py: このスクリプトは、インストールスクリプトによって /usr/local/sbin ディレクトリへとコピーされます。このスクリプトはinit対応版のFlash Playerポリシーサーバであり、ログはSTDERRに記録されます。このバージョンは複数のユーザ接続に対応できます。
  • flashpolicyd.init: このinitスクリプトは基本的なinitコマンドであるstartstopおよびrestartをサポートします。このファイルはインストーラスクリプトによって、 /etc/rc.d/init.d ディレクトリに /etc/rc.d/init.d/flashpolicyd としてインストールされます。このメソッドを使用した場合、当該サービスはルートとして実行されます。このスクリプトの冒頭で規定されている構成変数を検証し、適切なパス変数が用いられていることを確認するようにしてください。

Standaloneフォルダ

  • flashpolicyd.pl: スタンドアローン形式のこのシングルスレッドPerlスクリプトは、ユーザがCtrl+Cキーを押すまでループ状に実行され、一度につき1つのユーザ接続を受け付けます。
  • flashpolicyd.py: スタンドアローン形式のこのPythonスクリプトは、ユーザがCtrl+Cキーを押すまでループ状に実行されます。このバージョンは複数のユーザ接続に対応することができます。

xinetdにサービスを登録することで、管理者はいくつかのセキュリティコントロールを利用できるようになります。 たとえば、アクセスコントロールやDoS(denial-of-service)攻撃への保護対策が、Xinetdの構成を調整することで実装可能です。アドビが提供するスクリプトは、xinetdのセキュリティ設定に手を加えません。これは、これらの設定が各運用環境によって異なるからです。ただし、アドビでは、これらの機能の使用が適切なケースにおいては、これらの機能の利用を推奨します。

次のステップ

ソケットポリシーのリクエストとレスポンスは、単純な通信プロセスである一方で、ソケットポリシーファイルサーバの設定プロセスはインストール対象環境に左右されるものです。先頃登場したFlash Playerバージョンのソケットポリシーファイル関連の変更点ついて詳しくは、別途記事のFlash Player 9におけるポリシーファイルの変更点を参照してください。

著者について

Peleus Uhleyは、アドビのセキュアソフトウェアエンジニアリングチームのシニアセキュリティ研究者です。Peleusの主な仕事は、Flash PlayerやAdobe AIRなど、アドビのプラットフォームテクノロジーの支援です。Peleusは、アドビに入社するまでに、@stake、Symantec、Anonymizer, Incなどの企業の開発者およびセキュリティコンサルタントとして、セキュリティに関するスキルを身につけてきました。