Adobe AIR の HTML セキュリティ

Adobe AIR 1.0 およびそれ以降

このトピックでは、AIR HTML セキュリティアーキテクチャについて、およびインラインフレーム、フレーム、サンドボックスブリッジを使用して HTML ベースのアプリケーションを設定し、HTML コンテンツを SWF ベースのアプリケーションに安全に統合する方法について説明します。

ランタイムは、HTML および JavaScript の潜在的なセキュリティの脆弱性を克服するためのルールを適用し、メカニズムを提供します。同じルールは、アプリケーションを最初に JavaScript で記述する場合や HTML および JavaScript コンテンツを SWF ベースのアプリケーション内に読み込む場合にも適用されます。アプリケーションサンドボックスと非アプリケーションセキュリティサンドボックスのコンテンツは権限が異なります。コンテンツをインラインフレームまたはフレームに読み込むと、ランタイムによって安全な サンドボックスブリッジ メカニズムが提供されて、フレームまたはインラインフレーム内のコンテンツはアプリケーションセキュリティサンドボックス内のコンテンツと安全にやり取りできるようになります。

AIR SDK には、HTML コンテンツのレンダリングに使用する 3 つのクラスが用意されています。

HTMLLoader クラスは、JavaScript コードと AIR API との密接な統合を提供します。

StageWebView クラスは、HTML レンダリングクラスです。このクラスとホスト AIR アプリケーションとの統合は非常に限定されています。StageWebView クラスによって読み込まれたコンテンツは、アプリケーションセキュリティサンドボックスに配置されません。また、ホスト AIR アプリケーションでのデータへのアクセスや関数の呼び出しもできません。デスクトッププラットフォームの場合、StageWebView クラスは、Webkit をベースとしたビルトイン AIR HTML エンジンを使用します。このエンジンは HTMLLoader クラスでも使用されます。モバイルプラットフォームの場合、StageWebView クラスは、オペレーティングシステムが提供する HTML コントロールを使用します。したがって、モバイルプラットフォームの場合、StageWebView クラスには、システムの Web ブラウザーと同じセキュリティ上の考慮事項と脆弱性があります。

TextField クラスは、HTML テキストのストリングを表示できます。JavaScript を実行することはできませんが、リンクおよび外部から読み込まれたイメージをテキストに含めることはできます。

詳しくは、 セキュリティ関連の JavaScript エラーの回避 を参照してください。

HTML ベースのアプリケーションの設定の概要

フレームとインラインフレームは、AIR で HTML コンテンツを編成するための便利な構造を提供します。フレームを使用すると、データの永続化の維持とリモートコンテンツの安全な使用の両方が実現できます。

AIR 内の HTML では標準のページベースの編成が維持されるので、HTML コンテンツの最上位のフレームが別のページに「移動」すると HTML 環境は完全に更新されます。フレームとインラインフレームを使用すると、ブラウザーで実行されている Web アプリケーションと同じように、AIR でデータの永続性を維持できます。最上位のフレームでメインのアプリケーションオブジェクトを定義すると、フレームが新しいページに移動できない限り、それらのオブジェクトは永続化されます。アプリケーションの一時的な部分を読み込んで表示するには、子のフレームまたはインラインフレームを使用します(フレーム以外にも使用できるデータ永続化の維持方法は多数あります。例えば、Cookie、ローカル共有オブジェクト、ローカルファイルストレージ、暗号化されたファイルストア、ローカルデータベースストレージがあります)。

AIR では、HTML の実行可能なコードとデータとの間に通常のあいまいな境界が維持されるため、HTML 環境のトップフレームのコンテンツはアプリケーションサンドボックスに配置されます。ページの load イベント後は、テキストのストリングを実行可能なオブジェクトに変換する eval() などの操作は制限されます。この制限は、アプリケーションがリモートコンテンツを読み込まない場合でも適用されます。 そのような制限された操作を HTML コンテンツで実行できるようにするには、フレームまたはインラインフレームを使用して、コンテンツをアプリケーションとは別のサンドボックス内に配置する必要があります( eval() 関数に依存する JavaScript アプリケーションフレームワークを使用する場合も、サンドボックス化した子フレーム内でコンテンツを実行する必要が生じることがあります)。アプリケーションサンドボックスでの JavaScript に関する制限について詳しくは、 異なるサンドボックス内のコンテンツに対するコードの制限 を参照してください。

AIR 内の HTML ではリモートの安全でない可能性のあるコンテンツを読み込む機能が維持されるので、AIR では別のドメイン内のコンテンツとやり取りを回避するための同一生成元ポリシーを適用します。アプリケーションコンテンツと別のドメイン内のコンテンツ間のやり取りを許可するためには、親フレームと子フレーム間のインターフェイスとして機能するブリッジを設定します。

親子サンドボックス関係の設定

AIR では、HTML の frame および iframe エレメントに sandboxRoot 属性と documentRoot 属性を追加します。これらの属性を使用すると、アプリケーションコンテンツを別のドメインからのコンテンツとして扱うことができます。

属性

説明

sandboxRoot

フレームコンテンツを配置するサンドボックスとドメインを決定するために使用する URL。 file: http: または https: URL スキームを使用する必要があります。

documentRoot

フレームコンテンツの読み込み元の URL。 file: app: または app-storage: URL スキームを使用する必要があります。

次の例では、アプリケーションのサンドボックスサブディレクトリにインストールされているコンテンツをマップして、リモートサンドボックスおよび www.example.com ドメインで実行します。

<iframe 
    src="ui.html"  
    sandboxRoot="http://www.example.com/local/"  
    documentRoot="app:/sandbox/"> 
</iframe>

異なるサンドボックスまたはドメインでの親フレームと子フレーム間のブリッジの設定

AIR では、 childSandboxBridge および parentSandboxBridge プロパティを、任意の子フレームの window オブジェクトに追加します。これらのプロパティを使用すると、親フレームと子フレームの間のインターフェイスとして機能するブリッジを定義できます。各ブリッジは一方向に移動します。

childSandboxBridge childSandboxBridge プロパティを使用すると、子フレームで親フレーム内のコンテンツにインターフェイスを公開できます。インターフェイスを公開するには、 childSandbox プロパティを子フレーム内の関数またはオブジェクトに設定します。これで、親フレーム内のコンテンツからオブジェクトまたは関数にアクセスできます。次の例では、子フレームで実行中のスクリプトで、関数とプロパティを 1 つずつ含むオブジェクトをその親に公開する方法を示します。

var interface = {}; 
interface.calculatePrice = function(){ 
    return .45 + 1.20; 
} 
interface.storeID = "abc" 
window.childSandboxBridge = interface;

id として 「child」 が割り当てられたインラインフレーム内に子コンテンツがある場合、フレームの childSandboxBridge プロパティを読み取って親コンテンツからインターフェイスにアクセスできます。

var childInterface = document.getElementById("child").childSandboxBridge; 
air.trace(childInterface.calculatePrice()); //traces "1.65" 
air.trace(childInterface.storeID)); //traces "abc"

parentSandboxBridge parentSandboxBridge プロパティを使用すると、親フレームは子フレーム内のコンテンツにインターフェイスを公開できます。インターフェイスを公開するには、子フレームの parentSandbox プロパティを、親フレーム内の関数またはオブジェクトに設定します。これで、子フレーム内のコンテンツからオブジェクトまたは関数にアクセスできます。次の例では、親フレームで実行中のスクリプトで、save 関数を含むオブジェクトを子に公開する方法を示します。

var interface = {}; 
interface.save = function(text){ 
    var saveFile = air.File("app-storage:/save.txt"); 
    //write text to file 
} 
document.getElementById("child").parentSandboxBridge = interface;

このインターフェイスを使用すると、子フレーム内のコンテンツで、テキストを save.txt という名前のファイルに保存できます。ただし、コンテンツはファイルシステムに対する他のアクセス権を持つことはできません。一般的に、アプリケーションコンテンツは、他のサンドボックスにできる限り範囲の狭いインターフェイスを公開する必要があります。子コンテンツは、save 関数を次のように呼び出します。

var textToSave = "A string."; 
window.parentSandboxBridge.save(textToSave);

子コンテンツが parentSandboxBridge オブジェクトのプロパティを設定しようとすると、ランタイムによって SecurityError 例外がスローされます。親コンテンツが childSandboxBridge オブジェクトのプロパティを設定しようとすると、ランタイムによって SecurityError 例外がスローされます。

異なるサンドボックス内のコンテンツに対するコードの制限

このトピックの概要( Adobe AIR の HTML セキュリティ )で説明したように、ランタイムは、HTML および JavaScript の潜在的なセキュリティの脆弱性を克服するためのルールを適用し、メカニズムを提供します。ここでは、それらの制限について説明します。コードでこれらの制限された API を呼び出そうとすると、ランタイムによって、「Adobe AIR runtime security violation for JavaScript code in the application security sandbox」というメッセージのエラーがスローされます。

詳しくは、 セキュリティ関連の JavaScript エラーの回避 を参照してください。

JavaScript eval() 関数および同様の方法の使用に関する制限

アプリケーションセキュリティサンドボックス内の HTML コンテンツの場合は、コードが読み込まれた後( body エレメントの onload イベントが送出され、 onload ハンドラー関数が実行を完了した後)にストリングを実行可能コードに動的に変換できる API の使用について制限があります。これは、アプリケーションで、アプリケーション以外のソース(潜在的に安全でないネットワークドメインなど)から誤ってコードを挿入(および実行)されないようにするための制限です。

例えば、アプリケーションがリモートソースのストリングデータを使用して DOM エレメントの innerHTML プロパティに書き込みを行うと、ストリングには安全ではない操作を実行する可能性のある実行可能(JavaScript)コードが含まれている場合があります。ただし、コンテンツが読み込まれている間は、DOM にリモートストリングが挿入される可能性はありません。

1 つの制限は、JavaScript eval() 関数の使用に関するものです。アプリケーションサンドボックス内のコードが読み込まれ、onload イベントハンドラーの処理が完了した後は、 eval() 関数を制限された方法でのみ使用できます。 eval() 関数(アプリケーションセキュリティサンドボックスからコードが読み込まれた )の使用については、次のルールが適用されます。

  • リテラルを含む式は許可されます。次に、例を示します。

    eval("null"); 
    eval("3 + .14"); 
    eval("'foo'");
  • 次のようなオブジェクトリテラルは許可されます。

    { prop1: val1, prop2: val2 }
  • 次のようなオブジェクトリテラル setter/getter は、 禁止 されます。

    { get prop1() { ... }, set prop1(v) { ... } }
  • 次のような配列リテラルは許可されます。

    [ val1, val2, val3 ]
  • 次のようなプロパティの読み込みを含む式は、 禁止 されます。

    a.b.c
  • 関数の呼び出しは、 禁止 されます。

  • 関数の定義は、 禁止 されます。

  • プロパティの設定は、 禁止 されます。

  • 関数リテラルは、 禁止 されます。

ただし、コードの読み込み中、 onload イベントの前、および onload イベントハンドラー関数の実行中は、これらの制限はアプリケーションセキュリティサンドボックス内のコンテンツに適用されません。

例えば、コードが読み込まれた後に、次のコードを実行するとランタイムによって例外がスローされます。

eval("alert(44)"); 
eval("myFunction(44)"); 
eval("NativeApplication.applicationID");

eval() 関数を呼び出すときに作成されるような、動的に生成されたコードがアプリケーションサンドボックス内で許可されると、セキュリティリスクが発生します。例えば、アプリケーションがネットワークドメインから読み込まれたストリングを誤って実行し、そのストリングに悪意のあるコードが含まれている可能性があります。これは例えば、ユーザーのコンピューターのファイルを削除または変更するコードである可能性があります。または、信頼されないネットワークドメインにローカルファイルのコンテンツを送り返すコードである場合もあります。

動的なコードを生成する方法は次のとおりです。

  • eval() 関数を呼び出します。

  • innerHTML プロパティまたは DOM 関数を使用して、アプリケーションディレクトリ外のスクリプトを読み込む script タグを挿入します。

  • innerHTML プロパティまたは DOM 関数を使用して、( src 属性を使用してスクリプトを読み込むのではなく)インラインコードを含む script タグを挿入します。

  • src 属性を script タグに設定し、アプリケーションディレクトリ外にある JavaScript ファイルを読み込みます。

  • javascript URL スキームを使用します( href="javascript:alert('Test')" など)。

  • setInterval() または setTimout() 関数を使用します。この場合、(非同期で実行する関数を定義する)最初の関数が関数名ではなく(評価される)ストリングになります( setTimeout('x = 4', 1000) など)。

  • document.write() または document.writeln() を呼び出します。

アプリケーションセキュリティサンドボックス内のコードは、コンテンツを読み込んでいるときにのみこれらのメソッドを使用できます。

これらの制限で 回避されない のは、JSON オブジェクトリテラルを含む eval() の使用です。これによってアプリケーションコンテンツは、JSON JavaScript ライブラリで使用できます。ただし、オーバーロードされた JSON コード(イベントハンドラーを含む)の使用は制限されます。

その他の Ajax フレームワークおよび JavaScript コードライブラリの場合は、フレームワークまたはライブラリ内のコードが動的に生成されたコードに関するこれらの制限内で機能しているかどうかを確認します。制限に従っていない場合は、フレームワークまたはライブラリを使用するコンテンツを非アプリケーションセキュリティサンドボックスに含めます。詳しくは、 AIR における JavaScript の制限 および アプリケーションコンテンツと非アプリケーションコンテンツ間のスクリプト作成 を参照してください。アドビ システムズ社では、アプリケーションセキュリティサンドボックスをサポートする Ajax フレームワークのリストを http://www.adobe.com/products/jp/air/develop/ajax/features/ で管理しています。

アプリケーションセキュリティサンドボックスのコンテンツとは異なり、非アプリケーションセキュリティサンドボックスの JavaScript コンテンツは、 eval() 関数を呼び出して、動的に生成されたコードをいつでも実行できます。

AIR API へのアクセスに関する制限(非アプリケーションサンドボックス)

非アプリケーションサンドボックス内の JavaScript コードは、 window.runtime オブジェクトにアクセスできないので、AIR API を実行できません。非アプリケーションセキュリティサンドボックス内のコンテンツが次のコードを呼び出すと、アプリケーションは TypeError 例外をスローします。

try { 
    window.runtime.flash.system.NativeApplication.nativeApplication.exit(); 
}  
catch (e)  
{ 
    alert(e); 
}

例外のタイプが TypeError(未定義の値)であるのは、非アプリケーションサンドボックス内のコンテンツでは window.runtime オブジェクトが認識されず、未定義の値として示されるからです。

スクリプトブリッジを使用してランタイム機能を非アプリケーションサンドボックス内のコンテンツに公開できます。詳しくは、 アプリケーションコンテンツと非アプリケーションコンテンツ間のスクリプト作成 を参照してください。

XMLHttpRequest 呼び出しの使用に関する制限

アプリケーションセキュリティサンドボックス内の HTML コンテンツでは、HTML コンテンツが読み込まれている間や onLoad イベントの発生時に同期 XMLHttpRequest メソッドを使用してアプリケーションサンドボックス外からデータを読み込むことはできません。

デフォルトでは、非アプリケーションセキュリティサンドボックス内の HTML コンテンツで JavaScript XMLHttpRequest オブジェクトを使用して、リクエストを呼び出すドメイン以外のドメインからデータを読み込むことはできません。 frame または iframe タグには、 allowcrosscomainxhr 属性を含めることができます。この属性を null 値以外の値に設定すると、frame または iframe 内のコンテンツで Javascript XMLHttpRequest オブジェクトを使用して、リクエストを呼び出しているコードのドメイン以外のドメインからデータを読み込むことができます。

<iframe id="UI" 
    src="http://example.com/ui.html" 
    sandboxRoot="http://example.com/" 
    allowcrossDomainxhr="true" 
    documentRoot="app:/"> 
</iframe>

詳しくは、 異なるドメインのコンテンツ間のスクリプト作成 を参照してください。

CSS、frame、iframe および img エレメントの読み込みに関する制限(非アプリケーションサンドボックス内のコンテンツ)

リモート(ネットワーク)セキュリティサンドボックス内の HTML コンテンツは、CSS、 frame iframe および img エレメントをリモートサンドボックス(ネットワーク URL)からのみ読み込みます。

local-with-filesystem、local-with-networking または local-trusted サンドボックス内の HTML コンテンツは、CSS、frame、iframe および img コンテンツを(アプリケーションサンドボックスまたはリモートサンドボックスからではなく)ローカルサンドボックスからのみ読み込みます。

JavaScript window.open() メソッドの呼び出しに関する制限

JavaScript window.open() メソッドの呼び出しによって作成されたウィンドウに非アプリケーションセキュリティサンドボックスのコンテンツが表示される場合、ウィンドウのタイトルはメイン(起動している)ウィンドウのタイトルで始まり、その後にコロンが続きます。コードを使用してウィンドウのタイトルの部分を画面から移動することはできません。

非アプリケーションセキュリティサンドボックス内のコンテンツは、ユーザーがマウスやキーボードを操作すると発生するイベントに応じてのみ JavaScript window.open() メソッドを正しく呼び出すことができます。これにより、非アプリケーションコンテンツで、詐欺に使用される(フィッシング攻撃など)可能性のあるウィンドウが作成されることはなくなります。また、マウスイベントやキーボードイベントのイベントハンドラーでは、 window.open() メソッドを、遅延の後に( setTimeout() 関数を呼び出す場合など)実行されるように設定することはできません。

リモート(ネットワーク)サンドボックス内のコンテンツでは、リモートネットワークサンドボックス内のコンテンツを開く目的でのみ window.open() メソッドを使用できます。 window.open() メソッドを使用して、アプリケーションサンドボックスやローカルサンドボックスのコンテンツを開くことはできません。

local-with-filesystem、local-with-networking または local-trusted サンドボックス内のコンテンツ( セキュリティサンドボックス を参照)は、ローカルサンドボックスのコンテンツを開く目的でのみ window.open() メソッドを使用できます。 window.open() を使用してアプリケーションサンドボックスやリモートサンドボックスのコンテンツを開くことはできません。

制限付きコードを呼び出した場合のエラー

これらのセキュリティ制限によりサンドボックスで使用が制限されているコードを呼び出すと、ランタイムは JavaScript エラー「Adobe AIR runtime security violation for JavaScript code in the application security sandbox」を送出します。

詳しくは、 セキュリティ関連の JavaScript エラーの回避 を参照してください。

ストリングから HTML コンテンツを読み込む場合のサンドボックスによる保護

HTMLLoader クラスの loadString() メソッドを使用すると、実行時に HTML コンテンツを作成できます。ただし、安全でないインターネットソースから読み込んだデータを HTML コンテンツとして使用すると、データが壊れる場合があります。このため、デフォルトでは、 loadString() メソッドを使用して作成した HTML はアプリケーションサンドボックスに配置されず、AIR API にアクセスできません。ただし、HTMLLoader オブジェクトの placeLoadStringContentInApplicationSandbox プロパティを true に設定すると、 loadString() メソッドを使用して作成した HTML をアプリケーションサンドボックスに配置できます。詳しくは、 ストリングからの HTML コンテンツの読み込み を参照してください。