WPF 部分信頼セキュリティ
一般的に、インターネット アプリケーションでは、悪意による損害を防ぐため、重要なシステム リソースへの直接アクセスを制限する必要があります。 既定では、HTML およびクライアント側のスクリプト言語では、重要なシステム リソースにアクセスできません。 ブラウザーでホストされる Windows Presentation Foundation (WPF) アプリケーションは、ブラウザーから起動できるため、同様の一連の制限に準拠している必要があります。 これらの制限を適用するため、WPF ではコード アクセス セキュリティ (CAS) と ClickOnce の両方が使用されます (詳細については、「WPF のセキュリティ方針 - プラットフォーム セキュリティ」を参照してください)。 既定では、ブラウザーでホストされるアプリケーションは、インターネット、ローカル イントラネット、またはローカル コンピューターのどこから起動するかに関係なく、インターネット ゾーンの一連の CAS 権限が要求されます。 アクセス許可がフルセットで付与されていないアプリケーションは、部分信頼で実行されている、と言います。
WPF には、可能な限り多くの機能を部分信頼で安全にできるようにするさまざまなサポートが用意されています。また、CAS と共に、部分信頼プログラミングのサポートが追加されています。
このトピックは、次のセクションで構成されています。
WPF 機能の部分信頼のサポート
次の表は、インターネット ゾーンのアクセス許可セットの制限内で安全に使用できる Windows Presentation Foundation (WPF) の高度な機能を示しています。
表 1:部分信頼で安全な WPF 機能
機能分野 | 機能 |
---|---|
全般 | ブラウザー ウィンドウ 起点サイト アクセス IsolatedStorage (512KB 制限) UIAutomation プロバイダー コマンド実行 入力方式エディター (IME) タブレットのスタイラスとインク マウス キャプチャおよび移動イベントを使用した、シミュレートされたドラッグ アンド ドロップ OpenFileDialog XAML 逆シリアル化 (XamlReader.Load 経由) |
Web 統合 | ブラウザーのダウンロード ダイアログ ユーザーが開始したトップ レベルのナビゲーション mailto: リンク Uniform Resource Identifier パラメーター HTTPWebRequest IFRAME でホストされている WPF コンテンツ Frame を使用した同一サイトの HTML ページのホスト WebBrowser を使用した同一サイトの HTML ページのホスト Web サービス (ASMX) Web サービス (Windows Communication Foundation を使用) [スクリプティング] ドキュメント オブジェクト モデル |
ビジュアル | 2D と 3D アニメーション メディア (起点サイトとクロス ドメイン) イメージング/オーディオ/動画 |
読み取り | FlowDocument XPS ドキュメント 埋め込みフォントとシステム フォント CFF フォントと TrueType フォント |
編集 | スペル チェック RichTextBox プレーン テキストとインク クリップボードのサポート ユーザーが開始した貼り付け 選択したコンテンツのコピー |
コントロール | 一般的なコントロール |
この表では、大まかな WPF 機能について説明します。 より詳細な情報については、Windows SDK ドキュメントに記載されている、WPF の各メンバーで必要なアクセス許可を参照してください。 また、次の機能には、特別な考慮事項など、部分的な信頼の実行に関する詳細情報が含まれています。
XAML (「WPF の XAML」を参照)。
ポップアップ (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 が動作するには、Internet Explorer や旧バージョンの Firefox などの従来のブラウザーが必要です。 これらの古いブラウザーは、通常、Windows 10 や Windows 11 ではサポートされていません。 最新のブラウザーでは、セキュリティ リスクがあるため XBAP アプリに必要なテクノロジがサポートされなくなりました。 XBAP を有効にするプラグインはサポートされなくなりました。 詳細については、「ブラウザーでホストされる WPF アプリケーション (XBAP) についてよく寄せられる質問」を参照してください。
セキュリティ ゾーン | 動作 | 完全信頼を受け取るための操作 |
---|---|---|
ローカル コンピューター | 完全な信頼を自動的に受け取る | アクションは必要ありません。 |
イントラネットおよび信頼済みサイト | 完全な信頼のプロンプトを表示する | プロンプトにソースが表示されるように、証明書を使用して XBAP に署名します。 |
インターネット | "信頼されていません" というメッセージが表示され、失敗する | 証明書を使用して XBAP に署名します。 |
注意
前の表で説明した動作は、ClickOnce 信頼済み配置モデルに従わない完全な信頼の XBAP の動作です。
一般に、許可されているアクセス許可を超える可能性のあるコードは、おそらく、スタンドアロン アプリケーション間、およびブラウザーでホストされるアプリケーション間の両方で共有される共通コードです。 CAS と WPF は、このシナリオを管理するためのいくつかの手法を提供します。
CAS を使用してアクセス許可を検出する
場合によっては、ライブラリ アセンブリの共有コードをスタンドアロン アプリケーションと XBAP の両方で使用できます。 このような場合、コードによって、アプリケーションに付与されているアクセス許可セットよりも多くのアクセス許可を必要とする機能が実行される可能性があります。 アプリケーションでは、Microsoft .NET Framework セキュリティを使用して特定のアクセス許可があるかどうかを検出できます。 具体的には、必要なアクセス許可のインスタンスで Demand メソッドを呼び出すことによって、特定のアクセス許可があるかどうかをテストできます。 これを次の例に示します。この例には、ファイルをローカル ディスクに保存できるアクセス許可があるかどうかをクエリするコードが含まれています。
using System.IO;
using System.IO.IsolatedStorage;
using System.Security;
using System.Security.Permissions;
using System.Windows;
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;
}
}
Imports System.IO
Imports System.IO.IsolatedStorage
Imports System.Security
Imports System.Security.Permissions
Imports System.Windows
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
アプリケーションに必要なアクセス許可がない場合、Demand を呼び出すと、セキュリティ例外がスローされます。 それ以外の場合は、アクセス許可が付与されています。 IsPermissionGranted
はこの動作をカプセル化し、必要に応じて true
または false
を返します。
機能の適切な低下
コードに必要な操作を実行するためのアクセス許可があるかどうかを検出することは、異なるゾーンから実行できるコードにおいては重要です。 ゾーンを検出することもできますが、可能であれば、ユーザーに代替手段を提供することをお勧めします。 たとえば、完全信頼アプリケーションでは、通常、ユーザーは任意の場所にファイルを作成できますが、一方で部分信頼アプリケーションでは、分離ストレージにのみファイルを作成できます。 ファイルを作成するコードが、完全信頼 (スタンドアロン) アプリケーションと部分信頼 (ブラウザーでホストされる) アプリケーションの両方で共有されるアセンブリに存在し、両方のアプリケーションでユーザーがファイルを作成できるようにする場合は、適切な場所にファイルを作成する前に、共有コードが部分信頼または完全な信頼のどちらで実行されているかどうかを検出する必要があります。 次のコードは、これら両方を示しています。
using System.IO;
using System.IO.IsolatedStorage;
using System.Security;
using System.Security.Permissions;
using System.Windows;
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;
}
}
Imports System.IO
Imports System.IO.IsolatedStorage
Imports System.Security
Imports System.Security.Permissions
Imports System.Windows
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
多くの場合、部分信頼の代替を見つけることができるはずです。
イントラネットなどの制御された環境では、カスタム マネージド フレームワークをクライアント ベース全体でグローバル アセンブリ キャッシュ (GAC) にインストールできます。 これらのライブラリでは、完全な信頼を必要とするコードを実行できます。また、AllowPartiallyTrustedCallersAttribute を使用して、部分信頼のみ許可されているアプリケーションから参照できます (詳細については、セキュリティに関する記事と、「WPF のセキュリティ方針 - プラットフォーム セキュリティ」を参照してください)。
ブラウザー ホストの検出
アクセス許可ごとに確認する必要がある場合は、CAS を使用してアクセス許可を確認することが適切な方法です。 ただし、この手法では通常の処理の一部として例外をキャッチすることに依存していますが、これは一般的には推奨されず、パフォーマンスの問題が発生する可能性があります。 代わりに、XAML ブラウザー アプリケーション (XBAP) がインターネット ゾーンのサンドボックス内でのみ実行されている場合は、BrowserInteropHelper.IsBrowserHosted プロパティを使用できます。このプロパティは、XAML ブラウザー アプリケーション (XBAP) に対して true を返します。
警告
XBAP が動作するには、Internet Explorer や旧バージョンの Firefox などの従来のブラウザーが必要です。 これらの古いブラウザーは、通常、Windows 10 や Windows 11 ではサポートされていません。 最新のブラウザーでは、セキュリティ リスクがあるため XBAP アプリに必要なテクノロジがサポートされなくなりました。 XBAP を有効にするプラグインはサポートされなくなりました。 詳細については、「ブラウザーでホストされる WPF アプリケーション (XBAP) についてよく寄せられる質問」を参照してください。
Note
IsBrowserHosted は、アプリケーションがブラウザーで実行されているかどうかを識別するだけで、アプリケーションで実行されている一連のアクセス許可は識別されません。
アクセス許可の管理
既定では、XBAP は部分信頼 (既定のインターネット ゾーン アクセス許可セット) を使用して実行されます。 ただし、アプリケーションの要件によっては、一連のアクセス許可を既定値から変更することができます。 たとえば、XBAP をローカル イントラネットから起動した場合、次の表に示すように、引き上げられたアクセス許可セットを利用できます。
警告
XBAP が動作するには、Internet Explorer や旧バージョンの Firefox などの従来のブラウザーが必要です。 これらの古いブラウザーは、通常、Windows 10 や Windows 11 ではサポートされていません。 最新のブラウザーでは、セキュリティ リスクがあるため XBAP アプリに必要なテクノロジがサポートされなくなりました。 XBAP を有効にするプラグインはサポートされなくなりました。 詳細については、「ブラウザーでホストされる WPF アプリケーション (XBAP) についてよく寄せられる質問」を参照してください。
表 3:LocalIntranet とインターネットのアクセス許可
アクセス許可 | 属性 | LocalIntranet | インターネット |
---|---|---|---|
DNS | DNS サーバーへのアクセス | はい | いいえ |
環境変数 | 読み取り | はい | いいえ |
ファイル ダイアログ | 開く | はい | はい |
ファイル ダイアログ | 無制限 | はい | いいえ |
分離ストレージ | ユーザーによるアセンブリの分離 | はい | いいえ |
分離ストレージ | 不明な分離 | はい | はい |
分離ストレージ | 無制限のユーザー クォータ | はい | いいえ |
Media | 安全なオーディオ、動画、および画像 | はい | はい |
印刷 | 既定の印刷 | はい | いいえ |
印刷 | 安全な印刷 | はい | はい |
リフレクション | 出力 | はい | 無 |
セキュリティ | マネージド コードの実行 | はい | はい |
セキュリティ | 付与されたアクセス許可のアサート | はい | いいえ |
ユーザー インターフェイス | 無制限 | はい | いいえ |
ユーザー インターフェイス | 安全なトップ レベルのウィンドウ | はい | はい |
ユーザー インターフェイス | 独自のクリップボード | はい | はい |
Web ブラウザー | HTML への安全なフレーム ナビゲーション | はい | はい |
注意
切り取りと貼り付けは、ユーザーが開始したときに部分信頼でのみ許可されます。
アクセス許可を引き上げる必要がある場合は、プロジェクトの設定と ClickOnce アプリケーション マニフェストを変更する必要があります。 詳細については、「WPF XAML ブラウザー アプリケーションの概要」をご覧ください。 次のドキュメントも参照してください。
XBAP で完全な信頼が求められる場合は、同じツールを使用して、要求されたアクセス許可を引き上げることができます。 ただし、XBAP で完全な信頼が許可されるのは、ローカル コンピューター、イントラネット、またはブラウザーの信頼済みサイトまたは許可されたサイトに記載されている URL からこれがインストールされて起動している場合にのみです。 アプリケーションがイントラネットまたは信頼済みサイトからインストールされている場合、ユーザー向けに、アクセス許可が昇格された旨を通知する標準の ClickOnce プロンプトが表示されます。 ユーザーは、インストールを続行するか取り消すかを選択できます。
または、ClickOnce 信頼済みのデプロイ モデルを使用して、任意のセキュリティ ゾーンから完全に信頼された配置を行うことができます。 詳細については、「信頼されたアプリケーションの配置の概要」およびセキュリティに関する記事を参照してください。
関連項目
.NET Desktop feedback