接続文字列とその他の構成情報を保護する (C#)
ASP.NET アプリケーションは通常、構成情報を Web.config ファイルに保存します。 この情報の一部は機密情報であり、保護する必要があります。 既定では、このファイルは Web サイトの訪問者には提供されませんが、管理者またはハッカーが Web サーバーのファイル システムにアクセスしてファイルの内容を表示する可能性があります。 このチュートリアルでは、ASP.NET 2.0 で Web.config ファイルのセクションを暗号化することによって機密情報を保護する方法について説明します。
はじめに
ASP.NET アプリケーションの構成情報は、通常、 Web.config
という名前の XML ファイルに保存されます。 これらのチュートリアルの過程で、Web.config
を数回更新しました。 たとえば、最初のチュートリアルで型指定されたデータセット Northwind
を作成すると、接続文字列情報が Web.config
の <connectionStrings>
セクションに自動的に追加されました。 その後、マスター ページとサイト ナビゲーションのチュートリアルで、Web.config
を手動で更新し、プロジェクト内のすべての ASP.NET ページで DataWebControls
テーマを使用する必要があることを示す <pages>
要素を追加しました。
Web.config
には接続文字列などの機密データが含まれている可能性があるため、Web.config
の内容を安全に保ち、許可されていない閲覧者から隠すことが重要です。 既定では、拡張子 .config
が付いたファイルに対するすべての HTTP 要求は ASP.NET エンジンによって処理され、図 1 に示す "この種類のページは提供されません" というメッセージが返されます。 つまり、訪問者はブラウザーのアドレス バーに 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 には、選択した構成セクションをプログラムで簡単に暗号化および暗号化解除できる保護された構成システムが含まれています。
Note
このチュートリアルの最後に、ASP.NET アプリケーションからデータベースに接続するための Microsoft の推奨事項について説明します。 接続文字列の暗号化に加えて、安全な方法でデータベースに接続することで、システムを強化することもできます。
手順 1: ASP.NET 2.0 の保護された構成オプションを探索する
ASP.NET 2.0 には、構成情報を暗号化および暗号化解除するための保護された構成システムが含まれています。 これには、構成情報をプログラムで暗号化または暗号化解除するために使用できる .NET Framework のメソッドが含まれます。 保護された構成システムでは、プロバイダー モデルを使用します。これにより、開発者は、使用する暗号化実装を選択できます。
.NET Framework には、次の 2 つの保護された構成プロバイダーが付属しています。
RSAProtectedConfigurationProvider
- 暗号化と暗号化解除に非対称 RSA アルゴリズムを使用します。DPAPIProtectedConfigurationProvider
- 暗号化と暗号化解除に Windows データ保護 API (DPAPI) を使用します。
保護された構成システムはプロバイダー設計パターンを実装しているため、独自の保護された構成プロバイダーを作成し、それをアプリケーションにプラグインできます。 このプロセスの詳細については、「保護された構成プロバイダーの実装」を参照してください。
RSA および DPAPI プロバイダーは暗号化および暗号化解除ルーチンにキーを使用し、これらのキーはマシンレベルまたはユーザーレベルで保存できます。 マシンレベルのキーは、Web アプリケーションが独自の専用サーバー上で実行されるシナリオや、暗号化された情報を共有する必要がある複数のアプリケーションがサーバー上に存在するシナリオに最適です。 ユーザーレベルのキーは、同じサーバー上の他のアプリケーションがアプリケーションの保護された構成セクションを暗号化解除できないようにする必要がある共有ホスティング環境では、より安全なオプションです。
このチュートリアルの例では、DPAPI プロバイダーとマシンレベルのキーを使用します。 具体的には、Web.config
の <connectionStrings>
セクションの暗号化について説明しますが、保護された構成システムを使用して、ほとんどすべての Web.config
セクションを暗号化できます。 ユーザーレベル キーの使用または RSA プロバイダーの使用の詳細については、このチュートリアルの最後にある「もっと読む」セクションのリソースを参照してください。
Note
RSAProtectedConfigurationProvider
および DPAPIProtectedConfigurationProvider
プロバイダーは、それぞれ RsaProtectedConfigurationProvider
および DataProtectionConfigurationProvider
というプロバイダー名で machine.config
ファイルに登録されます。 構成情報を暗号化または暗号化解除する場合、実際の型名 (RSAProtectedConfigurationProvider
および DPAPIProtectedConfigurationProvider
) ではなく、適切なプロバイダー名 (RsaProtectedConfigurationProvider
または DataProtectionConfigurationProvider
) を指定する必要があります。 machine.config
ファイルは、$WINDOWS$\Microsoft.NET\Framework\version\CONFIG
フォルダーにあります。
手順 2: プログラムにより構成セクションを暗号化および暗号化解除する
数行のコードで、指定されたプロバイダーを使用して特定の構成セクションを暗号化または暗号化解除できます。 後述しますが、コードでは、適切な構成セクションをプログラムで参照し、その ProtectSection
または UnprotectSection
メソッドを呼び出してから、Save
メソッドを呼び出して変更内容を保存するだけです。 さらに、.NET Framework には、構成情報を暗号化および暗号化解除できる便利なコマンド ライン ユーティリティが含まれています。 手順 3 で、このコマンド ライン ユーティリティについて説明します。
構成情報をプログラムで保護する方法を説明するために、Web.config
の <connectionStrings>
セクションを暗号化および暗号化解除するためのボタンを含む ASP.NET ページを作成します。
まず、AdvancedDAL
フォルダーの EncryptingConfigSections.aspx
ページを開きます。 ツールボックスから TextBox コントロールをデザイナーにドラッグし、ID
プロパティを WebConfigContents
に、TextMode
プロパティを MultiLine
に、Width
および Rows
プロパティをそれぞれ 95% と 15 に設定します。 この TextBox コントロールには、Web.config
の内容が暗号化されているかどうかをすぐに確認できるように内容が表示されます。 もちろん、実際のアプリケーションでは、Web.config
の内容を表示する必要はありません。
テキスト ボックスの下に、EncryptConnStrings
と DecryptConnStrings
という名前の 2 つの Button コントロールを追加します。 Text プロパティを "接続文字列の暗号化" および "接続文字列の暗号化解除" に設定します。
この時点で、画面は図 2 のようになります。
図 2: ページに TextBox および 2 つの Button Web コントロールを追加する (クリックするとフルサイズの画像が表示されます)
次に、ページが最初に読み込まれたときに Web.config
の内容を読み込んで WebConfigContents
テキスト ボックスに表示するコードを記述する必要があります。 ページの分離コード クラスに次のコードを追加します。 このコードは、DisplayWebConfig
という名前のメソッドを追加し、Page.IsPostBack
が false
の場合に Page_Load
イベント ハンドラーからそれを呼び出します。
protected void Page_Load(object sender, EventArgs e)
{
// On the first page visit, call DisplayWebConfig method
if (!Page.IsPostBack)
DisplayWebConfig();
}
private void DisplayWebConfig()
{
// Reads in the contents of Web.config and displays them in the TextBox
StreamReader webConfigStream =
File.OpenText(Path.Combine(Request.PhysicalApplicationPath, "Web.config"));
string configContents = webConfigStream.ReadToEnd();
webConfigStream.Close();
WebConfigContents.Text = configContents;
}
DisplayWebConfig
メソッドは、File
クラスを使用してアプリケーションの Web.config
ファイルを開き、StreamReader
クラスを使用してその内容を文字列に読み取り、Path
クラスを使用して Web.config
ファイルへの物理パスを生成します。 これら 3 つのクラスはすべて System.IO
名前空間にあります。 したがって、分離コード クラスの先頭に using
System.IO
ステートメントを追加するか、またはこれらのクラス名の前に System.IO.
を付ける必要があります。
次に、2 つの Button コントロールの Click
イベントのイベント ハンドラーを追加し、DPAPI プロバイダーでマシンレベルのキーを使用して <connectionStrings>
セクションを暗号化および暗号化解除するために必要なコードを追加する必要があります。 デザイナーから、各ボタンをダブルクリックして、分離コード クラスに Click
イベント ハンドラーを追加し、次のコードを追加します。
protected void EncryptConnStrings_Click(object sender, EventArgs e)
{
// Get configuration information about Web.config
Configuration config =
WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
// Let's work with the <connectionStrings> section
ConfigurationSection connectionStrings = config.GetSection("connectionStrings");
if (connectionStrings != null)
// Only encrypt the section if it is not already protected
if (!connectionStrings.SectionInformation.IsProtected)
{
// Encrypt the <connectionStrings> section using the
// DataProtectionConfigurationProvider provider
connectionStrings.SectionInformation.ProtectSection(
"DataProtectionConfigurationProvider");
config.Save();
// Refresh the Web.config display
DisplayWebConfig();
}
}
protected void DecryptConnStrings_Click(object sender, EventArgs e)
{
// Get configuration information about Web.config
Configuration config =
WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
// Let's work with the <connectionStrings> section
ConfigurationSection connectionStrings =
config.GetSection("connectionStrings");
if (connectionStrings != null)
// Only decrypt the section if it is protected
if (connectionStrings.SectionInformation.IsProtected)
{
// Decrypt the <connectionStrings> section
connectionStrings.SectionInformation.UnprotectSection();
config.Save();
// Refresh the Web.config display
DisplayWebConfig();
}
}
2 つのイベント ハンドラーで使用されるコードはほぼ同じです。 どちらも、WebConfigurationManager
クラスの OpenWebConfiguration
メソッドを介して、現在のアプリケーションの Web.config
ファイルに関する情報を取得することから始まります。 このメソッドは、指定された仮想パスの Web 構成ファイルを返します。 次に、Configuration
クラスの GetSection(sectionName)
メソッドを介して Web.config
ファイルの <connectionStrings>
セクションにアクセスし、ConfigurationSection
オブジェクトを返します。
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 つの Button Web コントロールを追加する (クリックするとフルサイズの画像が表示されます)
次に、[接続文字列の暗号化] ボタンをクリックします。 要求の検証が有効になっている場合、WebConfigContents
テキスト ボックスからポストバックされたマークアップによって HttpRequestValidationException
が生成され、"潜在的に危険な Request.Form
値がクライアントから検出されました" というメッセージが表示されます。 ASP.NET 2.0 で既定で有効になっている要求の検証では、エンコードされていない HTML を含むポストバックが禁止されており、スクリプトインジェクション攻撃を防げるように設計されています。 このチェックは、ページまたはアプリケーションレベルで無効にすることができます。 このページでこれをオフにするには、@Page
ディレクティブで ValidateRequest
設定を false
に設定します。 @Page
ディレクティブは、ページの宣言型マークアップの上部にあります。
<%@ Page ValidateRequest="False" ... %>
要求の検証、その目的、ページおよびアプリケーションレベルで無効にする方法、およびマークアップを HTML エンコードする方法の詳細については、「要求の検証 - スクリプト攻撃の防止」を参照してください。
ページに対する要求の検証を無効にした後、もう一度 [接続文字列の暗号化] ボタンをクリックしてみてください。 ポストバック時に、構成ファイルにアクセスし、その <connectionStrings>
セクションが DPAPI プロバイダーを使用して暗号化されます。 その後、テキスト ボックスが更新され、新しい Web.config
の内容が表示されます。 図 4 に示すように、<connectionStrings>
情報が暗号化されるようになりました。
図 4: [接続文字列の暗号化] ボタンをクリックして <connectionString>
セクションを暗号化する (クリックするとフルサイズの画像が表示されます)
コンピューターで生成された暗号化された <connectionStrings>
セクションは次のとおりです。ただし、簡潔にするために、<CipherData>
要素の内容の一部は削除されています。
<connectionStrings
configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMnd8BFdERjHoAwE/...zChw==</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
Note
<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
section は暗号化する構成セクション (connectionStrings など)、physical_directory は Web アプリケーションのルート ディレクトリへの完全な物理パス、provider は使用する保護された構成プロバイダーの名前 (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_CS"
-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
Note
コンピューター固有のキーを使用する 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 認証を使用する接続文字列を示しています。 $CREDENTIAL_PLACEHOLDER$
は、パスワード キーと値のペアのプレースホルダーです。 資格情報が接続文字列内に埋め込まれていることに注意してください。
Server=serverName; Database=Northwind; uid=userID; $CREDENTIAL_PLACEHOLDER$
攻撃者がアプリケーションの Web.config
ファイルを表示できることを想像してみてください。 SQL 認証を使用してインターネット経由でアクセス可能なデータベースに接続する場合、攻撃者はこの接続文字列を使用して、SQL Management Studio または自分の Web サイトの ASP.NET ページからデータベースに接続できます。 この脅威を軽減するには、保護された構成システムを使用して Web.config
内の接続文字列情報を暗号化します。
Note
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 アプリケーションでの構成情報の暗号化
- 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 は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Teresa Murphy と Randy Schmidt でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 にmitchell@4GuysFromRolla.com行をドロップしてください。