ASP.NET アプリケーションは通常、構成情報を Web.config ファイルに保存します。 この情報の一部は機密情報であり、保護する必要があります。 既定では、このファイルは Web サイトの訪問者には提供されませんが、管理者またはハッカーが Web サーバーのファイル システムにアクセスしてファイルの内容を表示する可能性があります。 このチュートリアルでは、ASP.NET 2.0 で Web.config ファイルのセクションを暗号化することによって機密情報を保護する方法について説明します。
イントロダクション
ASP.NET アプリケーションの構成情報は、通常、 Web.config
という名前の XML ファイルに保存されます。 これらのチュートリアルの過程で、Web.config
を数回更新しました。 たとえば、Northwind
で型指定された DataSet を作成すると、接続文字列情報が Web.config
セクションの<connectionStrings>
に自動的に追加されました。 後で、マスター ページとサイト ナビゲーションのチュートリアルで、Web.config
を手動で更新し、プロジェクト内のすべての ASP.NET ページで<pages>
テーマを使用する必要があることを示すDataWebControls
要素を追加しました。
Web.config
には接続文字列などの機密データが含まれている可能性があるため、Web.config
の内容を安全に保ち、許可されていない閲覧者から隠すことが重要です。 既定では、拡張子 .config
が付いたファイルに対するすべての HTTP 要求は ASP.NET エンジンによって処理され、図 1 に示す "この種類のページは提供されません" というメッセージが返されます。 つまり、訪問者はブラウザーのアドレス バーに Web.config
と入力するだけでは、http://www.YourServer.com/Web.config ファイルの内容を表示できません。
ブラウザーから Web.config にアクセスすると、「この種類のページは提供されていません」というメッセージが表示される。
図 1: ブラウザーを使用して Web.config
にアクセスすると、「この種類のページは提供されていません」というメッセージが返されます (フルサイズの画像を表示するにはクリック)
しかし、攻撃者が Web.config
ファイルの内容を表示できるようにする別の悪用を見つけることができた場合はどうでしょうか。 攻撃者はこの情報を使って何ができるでしょうか。また、Web.config
内の機密情報をさらに保護するためにどのような手順を実行できるでしょうか。 幸いなことに、Web.config
のほとんどのセクションには機密情報は含まれていません。 ASP.NET ページで使用される既定のテーマの名前を攻撃者が知っている場合、どのような被害を及ぼす可能性があるでしょうか。
ただし、Web.config
の特定のセクションには、接続文字列、ユーザー名、パスワード、サーバー名、暗号化キーなどの機密情報が含まれている場合があります。 この情報は通常、次の Web.config
セクションにあります。
<appSettings>
<connectionStrings>
<identity>
<sessionState>
このチュートリアルでは、このような機密性の高い構成情報を保護するための手法について説明します。 後述しますが、.NET Framework バージョン 2.0 には、選択した構成セクションをプログラムで簡単に暗号化および暗号化解除できる保護された構成システムが含まれています。
注
このチュートリアルでは、ASP.NET アプリケーションからデータベースに接続するための Microsoft の推奨事項について説明します。 接続文字列の暗号化に加えて、安全な方法でデータベースに接続することで、システムを強化することもできます。
手順 1: ASP.NET 2.0 の保護された構成オプションを探索する
ASP.NET 2.0 には、構成情報を暗号化および暗号化解除するための保護された構成システムが含まれています。 これには、構成情報をプログラムで暗号化または暗号化解除するために使用できる .NET Framework のメソッドが含まれます。 保護された構成システムでは、プロバイダー モデルを使用します。これにより、開発者は、使用する暗号化実装を選択できます。
.NET Framework には、次の 2 つの保護された構成プロバイダーが付属しています。
-
RSAProtectedConfigurationProvider
- 暗号化と復号化に非対称 RSA アルゴリズム を使用します。 -
DPAPIProtectedConfigurationProvider
- 暗号化と暗号化解除に Windows Data Protection API (DPAPI) を使用します。
保護された構成システムはプロバイダー設計パターンを実装しているため、独自の保護された構成プロバイダーを作成し、それをアプリケーションにプラグインできます。 このプロセスの詳細については、「 保護された構成プロバイダーの実装 」を参照してください。
RSA および DPAPI プロバイダーは暗号化および暗号化解除ルーチンにキーを使用し、これらのキーはマシンレベルまたはユーザーレベルで保存できます。 マシンレベルのキーは、Web アプリケーションが独自の専用サーバー上で実行されるシナリオや、暗号化された情報を共有する必要がある複数のアプリケーションがサーバー上に存在するシナリオに最適です。 ユーザーレベルのキーは、同じサーバー上の他のアプリケーションがアプリケーションの保護された構成セクションを暗号化解除できないようにする必要がある共有ホスティング環境では、より安全なオプションです。
このチュートリアルの例では、DPAPI プロバイダーとマシンレベルのキーを使用します。 具体的には、<connectionStrings>
の Web.config
セクションの暗号化について説明しますが、保護された構成システムを使用して、ほとんどすべての Web.config
セクションを暗号化できます。 ユーザーレベル キーの使用または RSA プロバイダーの使用の詳細については、このチュートリアルの最後にある「もっと読む」セクションのリソースを参照してください。
注
RSAProtectedConfigurationProvider
および DPAPIProtectedConfigurationProvider
プロバイダーは、それぞれ machine.config
および RsaProtectedConfigurationProvider
というプロバイダー名で DataProtectionConfigurationProvider
ファイルに登録されます。 構成情報を暗号化または暗号化解除する場合、実際の型名 (RsaProtectedConfigurationProvider
および DataProtectionConfigurationProvider
) ではなく、適切なプロバイダー名 (RSAProtectedConfigurationProvider
または DPAPIProtectedConfigurationProvider
) を指定する必要があります。
machine.config
ファイルは、$WINDOWS$\Microsoft.NET\Framework\version\CONFIG
フォルダーにあります。
手順 2: プログラムにより構成セクションを暗号化および暗号化解除する
数行のコードで、指定されたプロバイダーを使用して特定の構成セクションを暗号化または暗号化解除できます。 後述しますが、コードでは、適切な構成セクションをプログラムで参照し、その ProtectSection
または UnprotectSection
メソッドを呼び出してから、Save
メソッドを呼び出して変更内容を保存するだけです。 さらに、.NET Framework には、構成情報を暗号化および暗号化解除できる便利なコマンド ライン ユーティリティが含まれています。 手順 3 で、このコマンド ライン ユーティリティについて説明します。
構成情報をプログラムで保護する方法を説明するために、<connectionStrings>
の Web.config
セクションを暗号化および暗号化解除するためのボタンを含む ASP.NET ページを作成します。
まず、EncryptingConfigSections.aspx
フォルダーの AdvancedDAL
ページを開きます。 ツールボックスから TextBox コントロールをデザイナーにドラッグし、ID
プロパティを WebConfigContents
に、TextMode
プロパティを MultiLine
に、Width
および Rows
プロパティをそれぞれ 95% と 15 に設定します。 この TextBox コントロールには、Web.config
の内容が暗号化されているかどうかをすぐに確認できるように内容が表示されます。 もちろん、実際のアプリケーションでは、Web.config
の内容を表示する必要はありません。
テキスト ボックスの下に、EncryptConnStrings
と DecryptConnStrings
という名前の 2 つの Button コントロールを追加します。 Text プロパティを "接続文字列の暗号化" および "接続文字列の暗号化解除" に設定します。
この時点で、画面は図 2 のようになります。
図 2: TextBox コントロールと 2 つのボタン Web コントロールをページに追加する (フルサイズの画像を表示する をクリックします)
次に、ページが最初に読み込まれたときに Web.config
の内容を読み込んで WebConfigContents
テキスト ボックスに表示するコードを記述する必要があります。 ページの分離コード クラスに次のコードを追加します。 このコードは、DisplayWebConfig
という名前のメソッドを追加し、Page_Load
が Page.IsPostBack
の場合に False
イベント ハンドラーからそれを呼び出します。
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
'On the first page visit, call DisplayWebConfig method
If Not Page.IsPostBack Then
DisplayWebConfig()
End If
End Sub
Private Sub DisplayWebConfig()
'Reads in the contents of Web.config and displays them in the TextBox
Dim webConfigStream As StreamReader = _
File.OpenText(Path.Combine(Request.PhysicalApplicationPath, "Web.config"))
Dim configContents As String = webConfigStream.ReadToEnd()
webConfigStream.Close()
WebConfigContents.Text = configContents
End Sub
DisplayWebConfig
メソッドは、File
クラスを使用してアプリケーションのWeb.config
ファイルを開き、StreamReader
クラスを使用して内容を文字列に読み込み、Path
クラスを使用してWeb.config
ファイルへの物理パスを生成します。 これら 3 つのクラスはすべて、System.IO
名前空間にあります。 そのため、コードビハインド クラスの先頭に Imports``System.IO
ステートメントを追加するか、またはこれらのクラス名の前に System.IO.
を付けてください。
次に、2 つの Button コントロールの Click
イベントのイベント ハンドラーを追加し、DPAPI プロバイダーでマシンレベルのキーを使用して <connectionStrings>
セクションを暗号化および暗号化解除するために必要なコードを追加する必要があります。 デザイナーから、各ボタンをダブルクリックして、分離コード クラスに Click
イベント ハンドラーを追加し、次のコードを追加します。
Protected Sub EncryptConnStrings_Click(sender As Object, e As EventArgs) _
Handles EncryptConnStrings.Click
'Get configuration information about Web.config
Dim config As Configuration = _
WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath)
' Let's work with the <connectionStrings> section
Dim connectionStrings As ConfigurationSection = _
config.GetSection("connectionStrings")
If connectionStrings IsNot Nothing Then
' Only encrypt the section if it is not already protected
If Not connectionStrings.SectionInformation.IsProtected Then
' Encrypt the <connectionStrings> section using the
' DataProtectionConfigurationProvider provider
connectionStrings.SectionInformation.ProtectSection( _
"DataProtectionConfigurationProvider")
config.Save()
' Refresh the Web.config display
DisplayWebConfig()
End If
End If
End Sub
Protected Sub DecryptConnStrings_Click(sender As Object, e As EventArgs) _
Handles DecryptConnStrings.Click
' Get configuration information about Web.config
Dim config As Configuration = _
WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath)
' Let's work with the <connectionStrings> section
Dim connectionStrings As ConfigurationSection = _
config.GetSection("connectionStrings")
If connectionStrings IsNot Nothing Then
' Only decrypt the section if it is protected
If connectionStrings.SectionInformation.IsProtected Then
' Decrypt the <connectionStrings> section
connectionStrings.SectionInformation.UnprotectSection()
config.Save()
' Refresh the Web.config display
DisplayWebConfig()
End If
End If
End Sub
2 つのイベント ハンドラーで使用されるコードはほぼ同じです。 どちらも、Web.config
クラスの WebConfigurationManager
メソッドを使用して、現在のアプリケーションのOpenWebConfiguration
ファイルに関する情報を取得することから始めます。 このメソッドは、指定された仮想パスの Web 構成ファイルを返します。 次に、Web.config
ファイルの <connectionStrings>
セクションにはConfiguration
の を使用してアクセスします。
ConfigurationSection
オブジェクトには、構成セクションに関する追加情報と機能を提供するSectionInformation
プロパティが含まれています。 上記のコードで示されているように、SectionInformation
プロパティの IsProtected
プロパティをチェックすることで、構成セクションが暗号化されているかどうかを判断できます。 さらに、SectionInformation
プロパティの ProtectSection(provider)
および UnprotectSection
メソッドを使用して、このセクションを暗号化または暗号化解除できます。
ProtectSection(provider)
メソッドは、暗号化時に使用する保護された構成プロバイダーの名前を指定する文字列を入力として受け入れます。
EncryptConnString
ボタンのイベント ハンドラーでは、DPAPI プロバイダーが使用されるように、DataProtectionConfigurationProvider を ProtectSection(provider)
メソッドに渡します。
UnprotectSection
メソッドは、構成セクションの暗号化に使用されたプロバイダーを特定できるため、入力パラメーターは必要ありません。
ProtectSection(provider)
またはUnprotectSection
メソッドを呼び出した後、変更を保持するには、Configuration
オブジェクトのSave
メソッドを呼び出す必要があります。 構成情報が暗号化または暗号化解除され、変更が保存されると、DisplayWebConfig
を呼び出して、更新された Web.config
の内容を TextBox コントロールに読み込みます。
上記のコードを入力したら、ブラウザーから EncryptingConfigSections.aspx
ページにアクセスしてテストします。 最初に、Web.config
の内容を一覧表示するページが表示され、<connectionStrings>
セクションがプレーンテキストで表示されます (図 3 を参照)。
図 3: TextBox コントロールと 2 つのボタン Web コントロールをページに追加する (フルサイズの画像を表示する をクリックします)
次に、[接続文字列の暗号化] ボタンをクリックします。 要求の検証が有効になっている場合、WebConfigContents
テキスト ボックスからポストバックされたマークアップによって HttpRequestValidationException
が生成され、"潜在的に危険な Request.Form
値がクライアントから検出されました" というメッセージが表示されます。 ASP.NET 2.0 で既定で有効になっている要求の検証では、エンコードされていない HTML を含むポストバックが禁止されており、スクリプトインジェクション攻撃を防げるように設計されています。 このチェックは、ページまたはアプリケーションレベルで無効にすることができます。 このページでこれをオフにするには、ValidateRequest
ディレクティブで False
設定を @Page
に設定します。
@Page
ディレクティブは、ページの宣言型マークアップの上部にあります。
<%@ Page ValidateRequest="False" ... %>
要求の検証、その目的、ページ レベルとアプリケーション レベルで無効にする方法、および HTML マークアップをエンコードする方法の詳細については、「 要求の検証 - スクリプト攻撃の防止」を参照してください。
ページに対する要求の検証を無効にした後、もう一度 [接続文字列の暗号化] ボタンをクリックしてみてください。 ポストバック時に、構成ファイルにアクセスし、その <connectionStrings>
セクションが DPAPI プロバイダーを使用して暗号化されます。 その後、テキスト ボックスが更新され、新しい Web.config
の内容が表示されます。 図 4 に示すように、<connectionStrings>
情報が暗号化されるようになりました。
図 4: [接続文字列の暗号化] ボタンをクリックすると、[ <connectionString>
] セクションが暗号化されます (フルサイズの画像を表示する をクリックします)
コンピューターで生成された暗号化された <connectionStrings>
セクションは次のとおりです。ただし、簡潔にするために、<CipherData>
要素の内容の一部は削除されています。
<connectionStrings
configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>
<CipherData>
<CipherValue>==</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
注
<connectionStrings>
要素は、暗号化を実行するために使用されるプロバイダー (DataProtectionConfigurationProvider
) を指定します。 この情報は、[接続文字列の暗号化解除] ボタンがクリックされたときに UnprotectSection
メソッドによって使用されます。
接続文字列情報は Web.config
からアクセスされると (記述したコード、SqlDataSource コントロール、または型指定されたデータセット内の TableAdapter から自動生成されたコードのいずれかによって)、自動的に暗号化解除されます。 つまり、暗号化された <connectionString>
セクションを暗号化解除するために、追加のコードやロジックを追加する必要はありません。 これを実証するには、現時点で前のチュートリアルの 1 つ (「基本レポート」セクションの Simple Display に関するチュートリアル (~/BasicReporting/SimpleDisplay.aspx
) など) を参照してください。 図 5 に示すように、チュートリアルは期待どおりに動作し、暗号化された接続文字列情報が ASP.NET ページによって自動的に暗号化解除されていることがわかります。
図 5: データ アクセス層が接続文字列情報を自動的に復号化する (フルサイズの画像を表示する をクリックします)
<connectionStrings>
セクションをプレーンテキスト表現に戻すには、[接続文字列の暗号化解除] ボタンをクリックします。 ポストバック時に、Web.config
内の接続文字列がプレーンテキストで表示されます。 この時点で、このページに初めてアクセスしたときと同じように画面が表示されます (図 3 を参照)。
手順 3: aspnet_regiis.exe を使用して構成セクションを暗号化する
.NET Framework には、$WINDOWS$\Microsoft.NET\Framework\version\
フォルダーにさまざまなコマンド ライン ツールが含まれています。 たとえば、 SQL キャッシュ依存関係の使用 に関するチュートリアルでは、 aspnet_regsql.exe
コマンド ライン ツールを使用して、SQL キャッシュの依存関係に必要なインフラストラクチャを追加する方法について説明しました。 このフォルダーのもう 1 つの便利なコマンド ライン ツールは、ASP.NET IIS 登録ツール (aspnet_regiis.exe
) です。 名前が示すように、ASP.NET IIS 登録ツールは主に、ASP.NET 2.0 アプリケーションを Microsoft のプロレベルの Web サーバーである IIS に登録するために使用されます。 IIS 関連の機能に加えて、ASP.NET IIS 登録ツールは、Web.config
内の指定された構成セクションを暗号化または暗号化解除するために使用することもできます。
次のステートメントは、aspnet_regiis.exe
コマンドライン ツールを使用して構成セクションを暗号化するために使用される一般的な構文を示しています。
aspnet_regiis.exe -pef section physical_directory -prov provider
セクション は暗号化する構成セクションです (connectionStrings など)。 physical_directory は Web アプリケーションのルート ディレクトリへの完全な物理パスであり、 プロバイダー は使用する保護された構成プロバイダーの名前です (DataProtectionConfigurationProvider など)。 または、Web アプリケーションが IIS に登録されている場合は、次の構文を使用して物理パスの代わりに仮想パスを入力できます。
aspnet_regiis.exe -pe section -app virtual_directory -prov provider
次の aspnet_regiis.exe
の例では、マシンレベルのキーを持つ DPAPI プロバイダーを使用して <connectionStrings>
セクションを暗号化します。
aspnet_regiis.exe -pef
"connectionStrings" "C:\Websites\ASPNET_Data_Tutorial_73_VB"
-prov "DataProtectionConfigurationProvider"
同様に、aspnet_regiis.exe
コマンドライン ツールを使用して構成セクションを暗号化解除することもできます。
-pef
スイッチの代わりに -pdf
を使用します (または -pe
の代わりに -pd
を使用します)。 また、暗号化を解除するときにプロバイダー名は必要ありません。
aspnet_regiis.exe -pdf section physical_directory
-- or --
aspnet_regiis.exe -pd section -app virtual_directory
注
コンピューター固有のキーを使用する DPAPI プロバイダーを使用しているため、Web ページが提供されているのと同じコンピューターから aspnet_regiis.exe
を実行する必要があります。 たとえば、ローカル開発マシンからこのコマンド ライン プログラムを実行し、暗号化された Web.config ファイルを運用サーバーにアップロードした場合、接続文字列情報は開発マシン固有のキーを使用して暗号化されているため、運用サーバーでは接続文字列情報を暗号化解除できません。 RSA プロバイダーについては、RSA キーを別のコンピューターにエクスポートできるため、この制限はありません。
データベース認証オプションを理解する
アプリケーションが Microsoft SQL Server データベースに対して SELECT
、INSERT
、UPDATE
、または DELETE
クエリを発行する前に、データベースはまず要求元を識別する必要があります。 このプロセスは "認証" と呼ばれ、SQL Server では 2 つの認証方法が提供されています。
-
Windows 認証 - アプリケーションが実行されているプロセスは、データベースとの通信に使用されます。 Visual Studio 2005 の ASP.NET 開発サーバーを介して ASP.NET アプリケーションを実行する場合、ASP.NET アプリケーションは現在ログオンしているユーザーの ID を想定します。 Microsoft インターネット インフォメーション サーバー (IIS) 上の ASP.NET アプリケーションの場合、ASP.NET アプリケーションは通常、
domainName``\MachineName
またはdomainName``\NETWORK SERVICE
の ID を想定しますが、これはカスタマイズ可能です。 - SQL 認証 - ユーザー ID とパスワードの値は、認証の資格情報として指定されます。 SQL 認証では、ユーザー ID とパスワードが接続文字列で提供されます。
Windows 認証はより安全であるため、SQL 認証よりも優先されます。 Windows 認証では、接続文字列にユーザー名とパスワードは含まれず、Web サーバーとデータベース サーバーが 2 台の異なるマシンに存在する場合、資格情報がネットワーク上にプレーンテキストで送信されることはありません。 ただし、SQL 認証では、認証資格情報は接続文字列にハードコーディングされ、Web サーバーからデータベース サーバーにプレーンテキストで送信されます。
これらのチュートリアルでは、Windows 認証を使用しています。 接続文字列を調べることで、使用されている認証モードを判別できます。 チュートリアルの Web.config
の接続文字列は次のとおりです。
Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\NORTHWND.MDF; Integrated Security=True; User Instance=True
Integrated Security=True であり、ユーザー名とパスワードがない場合は、Windows 認証が使用されていることを示します。 一部の接続文字列では、Integrated Security=True の代わりに Trusted Connection=Yes または Integrated Security=SSPI という用語が使用されますが、これら 3 つはすべて Windows 認証の使用を示しています。
次の例は、SQL 認証を使用する接続文字列を示しています。 接続文字列に埋め込まれている資格情報に注意してください。
Server=serverName; Database=Northwind; uid=userID; pwd=password
攻撃者がアプリケーションの Web.config
ファイルを表示できることを想像してみてください。 SQL 認証を使用してインターネット経由でアクセス可能なデータベースに接続する場合、攻撃者はこの接続文字列を使用して、SQL Management Studio または自分の Web サイトの ASP.NET ページからデータベースに接続できます。 この脅威を軽減するには、保護された構成システムを使用して Web.config
内の接続文字列情報を暗号化します。
注
SQL Server で使用できるさまざまな種類の認証の詳細については、「セキュリティで 保護された ASP.NET アプリケーションの構築: 認証、承認、およびセキュリティで保護された通信」を参照してください。 Windows と SQL の認証構文の違いを示す接続文字列の例については、 ConnectionStrings.com を参照してください。
概要
既定では、ASP.NET アプリケーション内の .config
拡張子を持つファイルには、ブラウザー経由でアクセスできません。 これらの種類のファイルは、データベース接続文字列、ユーザー名、パスワードなどの機密情報が含まれている可能性があるため返されません。 .NET 2.0 の保護された構成システムでは、指定した構成セクションを暗号化できるため、機密情報をさらに保護できます。 保護された構成プロバイダーが 2 つ組み込まれており、1 つは RSA アルゴリズムを使用し、もう 1 つは Windows データ保護 API (DPAPI) を使用します。
このチュートリアルでは、DPAPI プロバイダーを使用して構成設定を暗号化および暗号化解除する方法について説明しました。 これは、手順 2 で説明したようにプログラムで行うことも、手順 3 で説明した aspnet_regiis.exe
コマンド ライン ツールを使用して行うこともできます。 ユーザーレベルのキーを使用する方法、または代わりに RSA プロバイダーを使用する方法の詳細については、「もっと読む」セクションのリソースを参照してください。
プログラミングに満足!
もっと読む
この記事で説明したトピックの詳細については、次のリソースを参照してください。
- セキュリティで保護された ASP.NET アプリケーションの構築: 認証、承認、およびセキュリティで保護された通信
-
ASP.NET 2.0 での
Web.config
値の暗号化 - 方法: DPAPI を使用して ASP.NET 2.0 の構成セクションを暗号化する
- 方法: RSA を使用して ASP.NET 2.0 の構成セクションを暗号化する
- .NET 2.0 の構成 API
- Windows データ保護
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジを使用しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・セルフ ASP.NET 24時間で2.0です。 彼には mitchell@4GuysFromRolla.comで連絡できます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Teresa Murphy と Randy Schmidt でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、mitchell@4GuysFromRolla.comにメッセージを送ってください。