WPF 部分信頼セキュリティ
一般に、悪質な被害を防止するため、インターネット アプリケーションによる重要なシステム リソースへの直接アクセスは制限する必要があります。 既定では、HTML およびクライアント側のスクリプト言語は、重要なシステム リソースにはアクセスできません。 Windows Presentation Foundation (WPF) ブラウザー ホスト アプリケーションは、ブラウザーから起動できるため、同様に、一連の制限に従う必要があります。 この制限を適用するために、WPF は Code Access Security (CAS) と ClickOnce の両方に依存します (「WPF のセキュリティ方針 - プラットフォーム セキュリティ」を参照)。 既定では、ブラウザー ホスト アプリケーションは、インターネット、ローカル イントラネット、ローカル コンピューターのどこから起動されたかに関係なく、インターネット ゾーン CAS のアクセス許可セットを要求します。 無制限ではないアクセス許可の元で実行するアプリケーションは、部分信頼で実行しているものと見なされます。
WPF は、さまざまなサポートを提供し、最大限の機能を部分信頼で安全に使用できることを実現します。また、CAS と共に、部分信頼のプログラミングへの追加サポートを提供します。
このトピックは、次のセクションで構成されています。
WPF 機能の部分信頼サポート
部分信頼のプログラミング
アクセス許可の管理
WPF 機能の部分信頼サポート
次の表は、インターネット ゾーン アクセス許可セットの制限内で、安全に使用できる Windows Presentation Foundation (WPF) の高レベル機能の一覧です。
表 1 : 部分信頼で安全な WPF 機能
機能エリア |
機能 |
---|---|
全般 |
ブラウザー ウィンドウ 起点サイト アクセス IsolatedStorage (512 KB 制限) UIAutomation プロバイダー コマンド実行 入力方式エディター (IME) タブレット スタイラスとインク マウス キャプチャと移動イベントを使用してシミュレートされたドラッグ/ドロップ OpenFileDialog XAML 逆シリアル化 (XamlReader.Load 経由) |
Web 統合 |
ブラウザー ダウンロード ダイアログ トップレベル ユーザーが実行するナビゲーション mailto: リンク Uniform Resource Identifier パラメーター HTTPWebRequest IFRAME でホストされた WPF コンテンツ フレームを使用した同一サイトの HTML ページのホスト WebBrowser を使用した同一サイトの HTML ページのホスト Web サービス (ASMX) Web サービス (Windows Communication Foundation を使用) スクリプト ドキュメント オブジェクト モデル |
ビジュアル |
2D と 3D アニメーション メディア (起点サイトおよびドメイン間) イメージング/オーディオ/ビデオ |
読み取り |
FlowDocument XPS ドキュメント 埋め込みフォントとシステム フォント CFF フォントと TrueType フォント |
編集 |
スペル チェック RichTextBox プレーンテキストおよびインク クリップボード サポート ユーザーが実行する貼り付け 選択した内容のコピー |
コントロール |
コントロール全般 |
この表は、高レベルの WPF 機能を示しています。 詳細情報に関して Windows Software Development Kit (SDK) では、WPF の各メンバーが必要とするアクセス許可について文書化しています。 また、以下の機能については、特別な考慮事項など、部分信頼での実行に関するさらに詳細な情報があります。
XAML (「XAML の概要 (WPF)」を参照)。
ポップアップ (System.Windows.Controls.Primitives.Popup を参照)
ドラッグ アンド ドロップ (「ドラッグ アンド ドロップの概要」を参照)。
クリップボード (System.Windows.Clipboard を参照)
イメージング (System.Windows.Controls.Image を参照)
シリアル化 (XamlReader.Load、XamlWriter.Save を参照)
ファイルを開くダイアログ ボックス (Microsoft.Win32.OpenFileDialog を参照)。
次の表は、インターネット ゾーン アクセス許可セットの制限内では、安全に実行できない WPF 機能の一覧です。
表 2 : 部分信頼で安全でない WPF 機能
機能エリア |
機能 |
---|---|
全般 |
ウィンドウ (アプリケーションで定義したウィンドウおよびダイアログ ボックス) SaveFileDialog ファイル システム レジストリへのアクセス ドラッグ アンド ドロップ XAML シリアル化 (XamlWriter.Save 経由) UIAutomation クライアント ソース ウィンドウ アクセス (HwndHost) 完全な音声サポート Windows フォームの相互運用性 |
ビジュアル |
ビットマップ効果 イメージ エンコード |
編集 |
リッチ テキスト形式のクリップボード 完全な XAML サポート |
部分信頼のプログラミング
XBAP アプリケーションでは、コードが既定のアクセス許可セットを越える場合、セキュリティ ゾーンによって動作が異なります。 ユーザーがアプリケーションをインストールしようとすると警告が表示されることもあります。 ユーザーは、インストールを続行するか取り消すかを選択できます。 次の表は、各セキュリティ ゾーンのアプリケーション動作と、完全信頼を受け取るアプリケーションで行う必要のある操作を示しています。
セキュリティ ゾーン |
動作 |
完全信頼を受け取るための操作 |
---|---|---|
ローカル コンピューター |
完全信頼を自動的に受け取る |
アクションは必要ありません。 |
イントラネットおよび信頼されたサイト |
完全信頼のプロンプトを表示 |
ユーザーへのプロンプトにソースが表示されるように、証明書を使用して XBAP を署名します。 |
インターネット |
"信頼されていません" というメッセージが表示され、失敗する |
証明書を使用して XBAP に署名します。 |
メモ |
---|
前の表で説明した動作は、ClickOnce 信頼済み配置モデルに従っていない完全信頼の XBAP の動作です。 |
一般に、設定されているアクセス許可を超える可能性のあるコードは、スタンドアロン アプリケーションとブラウザー ホスト アプリケーションの間で共有される通常のコードと考えられます。 CAS と WPF には、このシナリオを処理するためのいくつかの手法が用意されています。
CAS を使用したアクセス許可の検出
状況によっては、ライブラリ アセンブリで共有されるコードを、スタンドアロン アプリケーションと XBAPs の両方で使用することができます。 この場合、コードは、アプリケーションに付与されているアクセス許可セットの制限よりも高い許可を要求する機能を実行する可能性があります。 アプリケーションは、Microsoft .NET Framework セキュリティを使用して、特定のアクセス許可を得ているかどうかを検出できます。 特に、必要なアクセス許可のインスタンスで Demand メソッドを呼び出して、特定のアクセス許可を持っているかどうかをテストすることができます。 これを次の例に示します。このコードでは、ローカル ディスクにファイルを保存できるかどうかを照会します。
Imports System.IO ' File, FileStream, StreamWriter
Imports System.IO.IsolatedStorage ' IsolatedStorageFile
Imports System.Security ' CodeAccesPermission, IsolatedStorageFileStream
Imports System.Security.Permissions ' FileIOPermission, FileIOPermissionAccess
Imports System.Windows ' MessageBox
Namespace SDKSample
Public Class FileHandling
Public Sub Save()
If IsPermissionGranted(New FileIOPermission(FileIOPermissionAccess.Write, "c:\newfile.txt")) Then
' Write to local disk
Using stream As FileStream = File.Create("c:\newfile.txt")
Using writer As New StreamWriter(stream)
writer.WriteLine("I can write to local disk.")
End Using
End Using
Else
MessageBox.Show("I can't write to local disk.")
End If
End Sub
' Detect whether or not this application has the requested permission
Private Function IsPermissionGranted(ByVal requestedPermission As CodeAccessPermission) As Boolean
Try
' Try and get this permission
requestedPermission.Demand()
Return True
Catch
Return False
End Try
End Function
...
End Class
End Namespace
using System.IO; // File, FileStream, StreamWriter
using System.IO.IsolatedStorage; // IsolatedStorageFile
using System.Security; // CodeAccesPermission, IsolatedStorageFileStream
using System.Security.Permissions; // FileIOPermission, FileIOPermissionAccess
using System.Windows; // MessageBox
namespace SDKSample
{
public class FileHandling
{
public void Save()
{
if (IsPermissionGranted(new FileIOPermission(FileIOPermissionAccess.Write, @"c:\newfile.txt")))
{
// Write to local disk
using (FileStream stream = File.Create(@"c:\newfile.txt"))
using (StreamWriter writer = new StreamWriter(stream))
{
writer.WriteLine("I can write to local disk.");
}
}
else
{
MessageBox.Show("I can't write to local disk.");
}
}
// Detect whether or not this application has the requested permission
bool IsPermissionGranted(CodeAccessPermission requestedPermission)
{
try
{
// Try and get this permission
requestedPermission.Demand();
return true;
}
catch
{
return false;
}
}
...
}
}
アプリケーションに必要なアクセス許可がない場合、Demand の呼び出しによって、セキュリティ例外がスローされます。 それ以外の場合は、アクセス許可が付与されます。 IsPermissionGranted は、この動作をカプセル化し、必要に応じて true または false を返します。
機能の正常な低下
コードに必要なアクセス許可があるかどうかを検出できることは、別のゾーンから実行できるコードにとって重要です。 ゾーンが 1 つであることを検出している間に、可能であれば、ユーザーに代替手段を提供する方がより望ましいでしょう。 たとえば、完全信頼アプリケーションを使用すると、通常、ユーザーは任意の場所にファイルを作成できますが、部分信頼アプリケーションでは、ファイルを作成できるのは分離ストレージだけです。 ファイルを作成するコードが、完全信頼 (スタンドアロン) アプリケーションと部分信頼 (ブラウザー ホスト) アプリケーションとで共有されるアセンブリ内にある場合、ユーザーが両方のアプリケーションでファイルを作成できるようにするには、適切な場所にファイルを作成する前に、この共有されるコードが、部分信頼で実行されているのか完全信頼で実行されているのかを検出する必要があります。 次のコードで両方の例を示します。
Imports System.IO ' File, FileStream, StreamWriter
Imports System.IO.IsolatedStorage ' IsolatedStorageFile
Imports System.Security ' CodeAccesPermission
Imports System.Security.Permissions ' FileIOPermission, FileIOPermissionAccess
Imports System.Windows ' MessageBox
Namespace SDKSample
Public Class FileHandlingGraceful
Public Sub Save()
If IsPermissionGranted(New FileIOPermission(FileIOPermissionAccess.Write, "c:\newfile.txt")) Then
' Write to local disk
Using stream As FileStream = File.Create("c:\newfile.txt")
Using writer As New StreamWriter(stream)
writer.WriteLine("I can write to local disk.")
End Using
End Using
Else
' Persist application-scope property to
' isolated storage
Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()
Using stream As New IsolatedStorageFileStream("newfile.txt", FileMode.Create, storage)
Using writer As New StreamWriter(stream)
writer.WriteLine("I can write to Isolated Storage")
End Using
End Using
End If
End Sub
' Detect whether or not this application has the requested permission
Private Function IsPermissionGranted(ByVal requestedPermission As CodeAccessPermission) As Boolean
Try
' Try and get this permission
requestedPermission.Demand()
Return True
Catch
Return False
End Try
End Function
...
End Class
End Namespace
using System.IO; // File, FileStream, StreamWriter
using System.IO.IsolatedStorage; // IsolatedStorageFile
using System.Security; // CodeAccesPermission
using System.Security.Permissions; // FileIOPermission, FileIOPermissionAccess
using System.Windows; // MessageBox
namespace SDKSample
{
public class FileHandlingGraceful
{
public void Save()
{
if (IsPermissionGranted(new FileIOPermission(FileIOPermissionAccess.Write, @"c:\newfile.txt")))
{
// Write to local disk
using (FileStream stream = File.Create(@"c:\newfile.txt"))
using (StreamWriter writer = new StreamWriter(stream))
{
writer.WriteLine("I can write to local disk.");
}
}
else
{
// Persist application-scope property to
// isolated storage
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
using (IsolatedStorageFileStream stream =
new IsolatedStorageFileStream("newfile.txt", FileMode.Create, storage))
using (StreamWriter writer = new StreamWriter(stream))
{
writer.WriteLine("I can write to Isolated Storage");
}
}
}
// Detect whether or not this application has the requested permission
bool IsPermissionGranted(CodeAccessPermission requestedPermission)
{
try
{
// Try and get this permission
requestedPermission.Demand();
return true;
}
catch
{
return false;
}
}
...
}
}
多くの場合、部分信頼の代替を見つける必要があります。
イントラネットなどの制御された環境では、カスタム マネージ フレームワークを、クライアント ベース全体にわたって、global assembly cache (GAC) にインストールすることができます。 このライブラリは、完全信頼を必要とするコードを実行することができ、AllowPartiallyTrustedCallersAttribute を使用することで、部分信頼だけを付与されているアプリケーションからも参照できます (詳細については、「セキュリティ (WPF)」および「WPF のセキュリティ方針 - プラットフォーム セキュリティ」を参照してください)。
ブラウザー ホストの検出
CAS を使用したアクセス許可の確認は、アクセス許可ごとの確認が必要な場合に適した手法です。 ただし、この手法は、通常の処理の一部として例外をキャッチすることに依存し、一般には推奨されません。また、パフォーマンスの問題を抱える可能性があります。 代わりに、XAML browser application (XBAP) がインターネット ゾーンのサンドボックス内でのみ実行される場合、BrowserInteropHelper.IsBrowserHosted プロパティを使用することができ、これは XAML browser applications (XBAPs) に true を返します。
メモ |
---|
IsBrowserHosted は、アプリケーションがブラウザーで実行されているかどうかを区別するだけで、実行中のアプリケーションに付与されているアクセス許可セットについての区別はしません。 |
アクセス許可の管理
既定では、XBAPs は、部分信頼 (既定のインターネット ゾーン アクセス許可セット) で実行されます。 ただし、アプリケーションの要求に応じて、アクセス許可セットを既定から変更することができます。 たとえば、XBAPs がローカル イントラネットから起動される場合、より高いアクセス許可セットを利用できます。これを次の表に示します。
表 3 : ローカル イントラネットのアクセス許可とインターネットのアクセス許可
アクセス許可 |
属性 |
ローカル イントラネット |
インターネット |
---|---|---|---|
DNS |
アクセス DNS サーバー |
○ |
X |
環境変数 |
読み取り |
○ |
X |
ファイル ダイアログ |
開く |
○ |
○ |
ファイル ダイアログ |
制限なし |
○ |
X |
分離ストレージ |
ユーザーによるアセンブリの分離 |
○ |
X |
分離ストレージ |
不明な分離 |
○ |
○ |
分離ストレージ |
無制限のユーザー クォータ |
○ |
X |
メディア |
安全なオーディオ、ビデオ、イメージ |
○ |
○ |
印刷 |
既定の印刷 |
○ |
X |
印刷 |
安全な印刷 |
○ |
○ |
リフレクション |
出力 |
○ |
X |
セキュリティ |
マネージ コードの実行 |
○ |
○ |
セキュリティ |
付与されたアクセス許可の Assert |
○ |
X |
ユーザー インターフェイス |
制限なし |
○ |
X |
ユーザー インターフェイス |
安全なトップレベル ウィンドウ |
○ |
○ |
ユーザー インターフェイス |
独自のクリップボード |
○ |
○ |
Web ブラウザー |
HTML への安全なフレーム ナビゲーション |
○ |
○ |
メモ |
---|
切り取りと貼り付けは、ユーザーが開始する部分信頼でのみ許可されます。 |
アクセス許可を増やす必要がある場合は、プロジェクト設定と ClickOnce アプリケーション マニフェストを変更する必要があります。 詳細については、「WPF XAML ブラウザー アプリケーションの概要」を参照してください。 次のドキュメントが役に立つこともあります。
XBAP が完全信頼を必要とする場合、同じツールを使用して要求されたアクセス許可を強化できます。 ただし、XBAP は、イントラネットのローカル コンピューター上にインストールされ、ローカル コンピューターから起動されるか、ブラウザーの信頼されたサイトまたは許可されたサイトのリストに含まれる URL から起動する場合にのみ、完全信頼を受け取ります。 アプリケーションがイントラネットまたは信頼されたサイトからインストールされる場合、アクセス許可が昇格されたことを通知する標準の ClickOnce プロンプトがユーザーに表示されます。 ユーザーは、インストールを続行するか取り消すかを選択できます。
または、任意のセキュリティ ゾーンで完全信頼配置用の ClickOnce 信頼済み配置モデルを使用することもできます。 詳細については、「信頼されたアプリケーションの配置の概要」および「セキュリティ (WPF)」を参照してください。