公開日: 2004年9月7日 | 最終更新日:
2004年9月7日
トピック
モジュールの内容
Web
ページとコントロールは、アプリケーションの防御の最前線であり、アプリケーションのセキュリティの侵害に没頭している攻撃者により集中的に調査されることがあります。多くの場合、こうした攻撃では、最終的にバックエンド
システムとデータ ストアが狙われます。
コード インジェクション、クロスサイト スクリプティング (XSS)
などのアプリケーション攻撃では、壊滅的な結果を招いたり、情報の漏えい、なりすまし、特権の昇格、リモート
コードの実行につながるおそれのある、サーバー側アプリケーションの脆弱性が利用されます。セキュリティ保護された Web
ページとコントロールを構築するには、このモジュールで説明する正しいプログラミング方法に従う必要があります。
このモジュールでは、ASP.NET
ページとコントロールの一般的な脅威および関連する対策を挙げて説明することから始めます。この後に、対処する必要があるアプリケーション
セキュリティ領域の包括的な一覧が続きます。このような領域には、入力検証、出力エンコード、認証、承認、偽装、機密性の高いデータの保護、安全なセッション管理、パラメータ改ざんの保護、例外管理などがあります。こうしたテクノロジは、多層防御セキュリティ
ソリューションの基本的な部分です。見過ごされがちですが、前述の脅威により、インフラストラクチャの安全性にかかわらず、攻撃者は間違いなくシステムのセキュリティを侵害できます。
ページのトップへ 目的
このモジュールの目的は次のとおりです。
| • | セキュリティ保護された ASP.NET ページとコントロールを設計する。 |
| • | 正規表現や他のテクノロジを使用してセキュリティ保護された検証コードを開発する。 |
| • | クロスサイト スクリプティング (XSS) を防御する。 |
| • | ユーザーを認証して承認する。 |
| • | セキュリティ保護されたフォーム認証を開発する。 |
| • | 例外の詳細がクライアントに届かないようにする。 |
| • | ASP.NET セッションの管理と保護を行う。 |
| • | パラメータ改ざんを防止する。 |
| • | コード インジェクション、セッション ハイジャック、なりすまし、パラメータ改ざん、ネットワーク盗聴、情報の漏えい、クロスサイト
スクリプティング (XSS)、Cookie
リプレイ攻撃などの一般的な脅威に対処するためにどの対策を適用するかを見分けます。 |
適用対象
このモジュールは、次の製品およびテクノロジに適用されます。
| • | Microsoft® Windows® 2000 Server および Microsoft Windows Server™
2003 |
| • | Microsoft .NET Framework 1.1 および ASP.NET
1.1 |
モジュールの使用方法
提示された安全なプログラミング方法のほかに、このガイドの対応するモジュールを活用すれば、セキュリティ保護された ASP.NET
ページとコントロールの作成に役立ちます。
| • | モジュール 19 「ASP.NET アプリケーションと Web
サービスをセキュリティ保護する」の手順を実行します。このモジュールは、Machine.config と Web.config
のセキュリティ保護された設定で ASP.NET を適切に構成するのに役立ちます。 |
| • | このガイドのチェックリスト セクションに記載されているチェックリストを使用します。「チェックリスト: ASP.NET
をセキュリティ保護する」では、このモジュールの推奨事項とモジュール 19
の推奨事項が結合されています。このガイダンスを適用していることを確認してください。 |
| • | ASP.NET
ページとコントロールに特有な脅威と攻撃を理解します。このモジュールのガイドラインに従って対策を適用します。 |
| • | モジュール 4 「セキュリティ保護された Web アプリケーションの設計ガイドライン」を参照してください。このモジュール
(モジュール10) の推奨事項の多くは、モジュール 4 で説明した設計ガイドラインに基づいています。 |
| • | 設計者は、このモジュールの「設計に関する考慮事項」セクションを利用する必要があります。 |
| • | 開発者は、このモジュールのガイダンスを開発プロセスに適用する必要があります。最上位のアプリケーション
レベルの攻撃の大多数がこの領域の脆弱性を利用するため、開発者は、入力データ検証に特に注意を払う必要があります。 |
| • | ASP.NET ページとコントロール
セキュリティを微調整するために、コントロールをプログラムの観点から学習します。 |
| • | 一般的な問題に取り組む手段としてアプリケーション脆弱性カテゴリを使用します。アプリケーション脆弱性カテゴリには、問題の取り組みやグループ化に役立つ方法が用意されています。 |
脅威とその対策
ほとんどの Web アプリケーション攻撃では、HTTP
要求の中で悪質な入力を渡す必要があります。攻撃の一般的な目的は、許可されていない操作をアプリケーションで強制的に実行させることや、アプリケーションの通常の操作を中断させることです。このため、徹底的な入力検証は、多くの攻撃に対して不可欠な対策であり、ASP.NET
Web ページとコントロールを開発するときの最優先事項でなければなりません。主要な脅威には、以下のようなものがあります。
| • | コード インジェクション |
| • | セッション ハイジャック |
| • | なりすまし |
| • | パラメータ改ざん |
| • | ネットワーク盗聴 |
| • | 情報の漏えい |
図 10.1 は、Web アプリケーションに対する最も一般的な脅威を示しています。
図 10.1
ASP.NET Web ページとコントロールに対する一般的な脅威
コード インジェクション
コード インジェクションは、攻撃者がアプリケーションのセキュリティ
コンテキストを使用して任意のコードを実行できる場合に行われます。アプリケーションが特権アカウントを使用して実行する場合に、このリスクは高まります。
攻撃
コード インジェクション攻撃は各種あります。たとえば、以下が挙げられます。
| • | クロスサイト スクリプティング: 悪質なスクリプトが、入力として Web
アプリケーションに送信されます。このスクリプトは、ユーザーのブラウザにエコー バックされ、そこで実行されます。 |
| • | バッファ オーバーフロー: マネージ コードのタイプ
セーフ検証によりリスクが大幅に低下しますが、それでもアプリケーションは、特にアンマネージ
コードを呼び出す場合に攻撃を受けるおそれがあります。バッファ オーバーフローでは、攻撃者が Web アプリケーション
プロセス内部で、そのセキュリティ コンテキストを利用して任意のコードを実行できます。 |
| • | SQL インジェクション: この攻撃は、脆弱なデータ アクセス
コードを標的にします。攻撃者は、対象とするクエリを変更する SQL 入力、またはデータベースにおいてまったく新しいクエリを実行する
SQL 入力を送信します。一般的にフォーム認証ログオン ページが標的になるのは、ユーザー
ストアを照会するためにユーザー名とパスワードが使用されるためです。 |
脆弱性
コード インジェクション攻撃の成功につながる脆弱性には、以下のようなものがあります。
| • | 入力検証またはクライアント側入力検証に関する信頼性が不十分または欠落している。 |
| • | HTML 出力に検証されていない入力が含まれる。 |
| • | 入力されたパラメータを使用しない SQL ステートメントを動的に作成する。 |
| • | 過剰な特権を持つプロセス アカウントとデータベース ログオンを利用する。 |
対策
以下の対策を行えば、コード インジェクションを防止できます。
| • | 攻撃者がスクリプト コードを注入したり、バッファ
オーバーフローを発生させたりできないように、入力を検証します。 |
| • | 入力を含むすべての出力をエンコードします。このようにすれば、悪質なスクリプト
タグが挿入されていても、クライアントのブラウザでコードとして解釈されるのを防止できます。 |
| • | 悪質な SQL 入力がデータベースで実行可能なステートメントとして処理されないように、パラメータを受け入れるストアド
プロシージャを使用します。 |
| • | 最低限の特権プロセスと偽装アカウントを使用します。このようにすれば、リスクを軽減し、攻撃者がアプリケーションのセキュリティ
コンテキストを利用してコードを実行するようにした場合でも、被害を少なくすることができます。 |
セッション ハイジャック
"セッション ハイジャック" は、攻撃者が認証トークンを獲得して別のユーザーのセッションを制御する場合に発生します。認証トークンは、一般に
Cookie または URL
に格納されます。攻撃者が認証トークンを獲得した場合は、それを要求と共にアプリケーションに送信できます。アプリケーションでは、この要求を正当なユーザーのセッションに関連付けます。そのため、このセッションを利用すれば、攻撃者は、認証済みアクセスを必要とする、アプリケーションの制限区域にアクセスできます。その結果、攻撃者は正当なユーザーの識別情報と特権を受け継ぎます。
脆弱性
Web ページとコントロールがセッション ハイジャックの影響を受けやすくなる一般的な脆弱性には、以下のようなものがあります。
| • | URL 内の保護されていないセッション識別子 |
| • | 個人情報 Cookie と認証 Cookie の混在 |
| • | 暗号化されていないリンク経由で渡される認証 Cookie |
攻撃
セッション ハイジャック攻撃には、以下のようなものがあります。
| • | Cookie リプレイ: 攻撃者は、認証 Cookie
を捕捉するために、ネットワーク監視ソフトウェアを使用するか、他の何らかの手段を利用します。たとえば、XSS
スクリプティング脆弱性を悪用します。 |
| • | クエリ文字列操作: 悪質なユーザーが、URL
クエリ文字列で明確に表示されているセッション識別子を変更します。 |
対策
以下の対策を採用すれば、セッション ハイジャックを防止できます。
| • | 個人情報 Cookie と認証 Cookie を分離します。 |
| • | HTTPS 接続経由の場合にのみ認証 Cookie を送信します。 |
| • | クエリ文字列では認証済みユーザーを表すセッション識別子を引き渡しません。 |
| • | 発注、送金などの重要な操作を実行する前にユーザーを再認証します。 |
なりすまし
"なりすまし" は、悪質なユーザーが、アプリケーションにアクセスできるように、正当なユーザーのふりをする場合に発生します。
脆弱性
Web ページとコントロールがなりすまし攻撃の影響を受けやすくなる一般的な脆弱性には、以下のようなものがあります。
| • | 暗号化されていないリンク経由で渡される認証資格情報 |
| • | 暗号化されていないリンク経由で渡される認証 Cookie |
| • | 脆弱なパスワードとポリシー |
| • | ユーザー ストア内の脆弱な資格情報ストレージ |
攻撃
なりすまし攻撃には、以下のようなものがあります。
| • | Cookie リプレイ: 攻撃者は、認証 Cookie
を捕捉するために、ネットワーク監視ソフトウェアを使用するか、XSS 攻撃を利用します。その結果、攻撃者は Cookie
をアプリケーションに送信し、偽装アクセスします。 |
| • | ブルート フォース パスワード攻撃:
攻撃者が、ユーザー名とパスワードの組み合わせを何度も試します。 |
| • | 辞書攻撃: この自動化したブルート フォース
パスワード攻撃では、辞書中のあらゆる語をパスワードとして試します。 |
対策
以下の対策を採用すれば、なりすましを防止できます。
| • | HTTPS 接続経由の場合にのみ認証資格情報と認証 Cookie を送信します。 |
| • | 強固なパスワードを指定します。正規表現を利用すれば、ユーザー指定のパスワードを適度に複雑にするという要件を確実に満たすことができます。 |
| • | パスワード検証をデータベースに格納します。辞書攻撃のリスクを軽減するためにランダムな salt 値と組み合わせた非可逆パスワード
ハッシュを格納します。 |
パスワード ハッシュと他のシークレットをデータベースに格納する方法の詳細については、モジュール 14 「セキュリティ保護されたデータ
アクセスを構築する」を参照してください。
パラメータ改ざん
パラメータとは、ネットワーク経由でクライアントからサーバーに渡されるデータ項目のことです。パラメータには、フォーム
フィールド、クエリ文字列、表示状態、Cookie、HTTP
ヘッダーなどがあります。機密性の高いデータ、またはサーバーでのセキュリティ意思決定に使用されるデータが、保護されていないパラメータを使用して渡される場合、アプリケーションは、情報の漏えいまたは許可されていないアクセスに対して潜在的に脆弱です。
脆弱性
パラメータ改ざんにつながる脆弱性には、以下のものがあります。
| • | 機密性の高いデータを含む隠しフォーム フィールドまたはクエリ文字列の使用 |
| • | 暗号化されていない接続でのセキュリティに関係するデータを含む Cookie の転送 |
攻撃
パラメータ改ざん攻撃には、以下のようなものがあります。
| • | Cookie リプレイ攻撃: 攻撃者は、Cookie
を捕捉して変更し、それをアプリケーションに対して再利用します。このため、Cookie
にサーバーでの認証または承認に使用されるデータが含まれている場合は、簡単になりすましや特権の昇格につながるおそれがあります。 |
| • | 隠しフォーム フィールドの操作:
こうしたフィールドには、サーバーでのセキュリティ意思決定に使用されるデータが含まれています。 |
| • | クエリ文字列パラメータの改ざん: |
対策
以下の対策を採用すれば、パラメータ改ざんを防止できます。
| • | クライアント側の状態管理オプションを利用しません。表示状態、Cookie、クエリ文字列、または隠しフォーム
フィールドのようなクライアント側の状態管理オプションのいずれかを使用して機密性の高いデータを格納するのは避けます。 |
| • | 機密性の高いデータはサーバーに格納します。サーバーで保持されている機密性の高いデータ項目にユーザーのセッションを関連付けるには、セッション
トークンを使用します。 |
| • | セッション トークンを保護するには、メッセージ認証コード (MAC)
を使用します。このコードをサーバーの認証、承認、およびビジネス
ロジックと対にして、トークンが再利用されないようにします。 |
ネットワーク盗聴
"ネットワーク盗聴" では、ネットワーク監視ソフトウェアを使用してブラウザと Web
サーバーの間で送信されるデータのパケットを追跡する方法を必要とします。ネットワーク盗聴は、アプリケーション固有の機密データの漏えい、ログオン資格情報の取得、または認証
Cookie の捕捉につながるおそれがあります。
脆弱性
ネットワーク盗聴の成功につながる脆弱性には、以下のようなものがあります。
| • | 機密性の高いデータを送信するときの暗号化の欠如 |
| • | 暗号化されていないチャンネルでの認証 Cookie の送信 |
攻撃
ネットワーク盗聴攻撃は、トラフィックを捕捉するためにネットワーク上に配備されているパケット盗聴ツールを使用して実行されます。
対策
ネットワーク盗聴に対抗するには、Secure Sockets Layer (SSL) を利用して、ブラウザと Web
サーバーの間に暗号化された通信チャンネルを用意します。ネットワーク経由で資格情報、認証チケット、または機密性の高いアプリケーション
データを送信するときは SSL を利用する必要があります。
情報の漏えい
"情報の漏えい" は、攻撃者が例外条件を発生させる方法を探すために Web
ページを調査するときに生じます。この方法を攻撃者が有意義に活用できる理由は、一般に例外の詳細が HTML
として返されたり、ブラウザで表示されることによって、データベース接続文字列、データベース名、データベース スキーマ情報、SQL
ステートメント、およびオペレーティング システムとプラットフォームのバージョンを含むスタック
トレースのような非常に有用な情報が明かされるためです。
脆弱性
情報の漏えいにつながる脆弱性には、以下のようなものがあります。
| • | 脆弱な例外処理。 |
| • | 未処理の例外詳細がクライアントに送信される。 |
攻撃
情報の漏えいが生じるおそれのある攻撃は数多くあります。たとえば、以下が挙げられます。
| • | バッファ オーバーフロー。 |
| • | 無効な入力を故意に送信。 |
対策
情報の漏えいを防止するには、以下のようにします。
| • | 構造化された例外処理を使用します。 |
| • | クライアントに一般的なエラー ページを返します。 |
| • | 害のない一般的なエラー メッセージを含む既定のリダイレクト ページを使用します。 |
設計に関する考慮事項
Web ページとコントロールを開発する前に、多くの重要な問題を設計時に考慮する必要があります。主な考慮事項は、以下のとおりです。
| • | サーバー側の入力検証を利用します。 |
| • | Web サイトを分割します。 |
| • | リソース アクセスに使用される識別情報を考慮します。 |
| • | 資格情報と認証チケットを保護します。 |
| • | 安全に失敗します。 |
| • | 承認レベルの精度について検討します。 |
| • | Web コントロールとユーザー コントロールを別々のアセンブリに配置します。 |
| • | リソース アクセス コードを別々のアセンブリに配置します。 |
サーバー側の入力検証を利用する
設計時に、Web ページとコントロールで処理するユーザー入力の各種ソースをすべて指定します。ソースには、バックエンド データ
ソースからのデータのほかに、Web ユーザーから受信するフォーム フィールド、クエリ文字列、Cookie も含まれます。Web
ユーザーは、明らかにアプリケーションの信頼境界外に存在するので、該当するソースからのすべての入力をサーバーで検証する必要があります。バックエンド
データ
ソースから受信したデータを確実に信頼できない限り、そのデータをクライアントに送信する前に検証して不適切な部分を削除する必要があります。簡単に回避されるため、実際のソリューションでクライアント側の検証を利用していないことを確認してください。
Web サイトを分割する
Web
サイト設計では、公的にアクセス可能な区域と認証済みアクセスを必要とする制限区域とを明確に区別する必要があります。認証済みアクセスを必要とし、クレジット
カード番号のような機密性の高いデータを送信する、従来の電子商取引 Web
サイトのチェックアウト機能などの制限されたページを保持するには、アプリケーションの仮想ルート
ディレクトリの下にある個々のサブディレクトリを使用します。サブディレクトリを個々に使用すれば、SSL を要求してもサイト全体に SSL
パフォーマンス オーバーヘッドが生じることなく、さらにセキュリティを強化できます。また、認証 Cookie の送信を HTTPS
接続に制限することによって、セッション ハイジャックのリスクを軽減することもできます。図 10.2 は、一般的な分割を示しています。
図 10.2
公共区域と保護区域に分割された Web サイト
図 10.2 の制限されたサブフォルダは、インターネット インフォメーション サービス (IIS) で SSL
アクセスを要求するように構成されていることに注意してください。Web.config の最初の <authorization>
要素は、すべてのユーザーが公開区域にアクセスできるようにしますが、2
番目の要素は、認証されていないユーザーが保護されたサブフォルダの内容にアクセスできないようにし、ログオンを強制実行します。
認証 Cookie が HTTPS 接続の場合にのみ渡されるように認証 Cookie
を制限する方法、および制限されたページと制限されていないページの間を移動する方法の詳細については、このモジュールの「認証」の「移動に絶対
URL を使用する」を参照してください。
リソース アクセスに使用される識別情報を考慮する
既定では、ASP.NET アプリケーションは偽装しないので、最低限の特権を持つ ASPNET プロセス アカウントが、ASP.NET Web
アプリケーションの実行とリソース アクセスに使用されます。既定値は推奨された構成です。ただし、リソース アクセスに異なる Windows
セキュリティ コンテキストを使用した方がよい場合がいくつかあります。たとえば、以下が挙げられます。
| • | 同一サーバーで複数のアプリケーションをホストする場合 IIS
を使用して各アプリケーションを構成すれば、別の匿名インターネット ユーザー
アカウントを使用して偽装を可能にすることができます。各アプリケーションには、リソース
アクセス用の異なる識別情報が設定されます。この方法の詳細については、モジュール 20 「複数の Web
アプリケーションをホストする」を参照してください。 |
| • | 特定の認証要件でリモート リソースにアクセスする場合 特定のリモート リソース (ファイル共有など)
にアクセスする必要があり、使用する特定の Windows アカウントが指定されている場合は、このアカウントをアプリケーションの匿名
Web ユーザー アカウントとして使用できます。その結果、特定のリモート
リソースにアクセスする前にプログラムで偽装を利用できます。詳細については、このモジュールで後述する「偽装」を参照してください。 |
資格情報と認証チケットを保護する
設計時に、資格情報と認証チケットの保護方法を考慮に入れる必要があります。資格情報がネットワークで渡される場合や、構成ファイルなどの固定ストアに存在している間は、資格情報を保護する必要があります。認証チケットは、ハイジャック攻撃を受けやすいため、ネットワーク上で保護する必要があります。これは、暗号化によって解決できます。SSL
または IPSec を利用すれば、ネットワーク上で資格情報とチケットを保護できます。また、DPAPI
は、構成ファイル内の資格情報を暗号化するための優れたソリューションを提供します。
安全に失敗する
アプリケーションが回復不可能な例外条件で失敗した場合は、そのアプリケーションが安全に失敗し、システムが広く開放されたままになっていないことを確認します。悪質なユーザーにとって貴重な例外詳細をクライアントに送信できないようになっており、代わりに一般的なエラー
ページを返すようになっていることを確認してください。また、メソッド エラー
コードを利用するのではなく、構造化された例外処理によってエラーを処理するように計画してください。
承認レベルの精度を検討する
サイトの認証された部分で利用する認証の精度を検討します。認証を必要とするようにディレクトリを構成した場合は、そのディレクトリ内のページにすべてのユーザーが同等にアクセスできるようにする必要があるかどうかを考慮します。必要な場合は、個々の
<location> 要素内で複数の <authorization>
要素を使用して、識別情報、または一般的に呼び出し側のロール メンバシップに基づいて個々のページにさまざまな認証規則を適用できます。
たとえば、同じディレクトリ内の 2 つのページに Web.config で <allow> と <deny>
という別々の要素を設定できます。
Web コントロールとユーザー コントロールを別々のアセンブリに配置する
Web コントロールとユーザー コントロールをそれぞれ独自のアセンブリに挿入した場合は、コード アクセス セキュリティ
ポリシーを利用すれば、アセンブリごとにセキュリティを個々に構成できます。これにより、柔軟性の高い管理を行うことができます。つまり、1
つのコントロールの要件を満たすだけのためにすべてのコントロールに拡張アクセス許可を付与する必要はありません。
リソース アクセス コードを別々のアセンブリに配置する
個々のアセンブリを使用して、リソース アクセス コードをページ クラスのイベントハンドラに埋め込むのではなくページ
クラスから呼び出します。これにより、コード アクセス セキュリティ ポリシーの柔軟性が大幅に高まります。また、この方法は、特に部分的に信頼できる
Web アプリケーションを作成する場合に重要です。詳細については、モジュール 9 「ASP.NET でコード アクセス
セキュリティを使用する」を参照してください。
入力検証
入力の型、長さ、形式、または範囲に関する前提に根拠がない場合は、アプリケーションを堅牢にすることはできません。前提に根拠がないことを攻撃者が発見すると、入力検証がセキュリティ問題になる場合があります。その結果、攻撃者は、アプリケーションのセキュリティを侵害するように巧妙に作成した入力を設定できます。ユーザー入力に対する信頼性の欠如は、Web
アプリケーションにおける最も一般的かつ致命的な脆弱性の 1 つです。
制限した後、不適切な部分を削除する
入力を制限して開始し、型、長さ、形式、および範囲の検証によって既知の正常なデータを確認します。場合によっては、入力の不適切な部分を削除し、潜在的に悪質な入力を安全にすることも必要です。たとえば、アプリケーションが自由形式入力フィールド
(コメント フィールドなど) をサポートしている場合は、特定の "安全な" HTML 要素 (<b>、<i> など)
を許可し、他のあらゆる HTML
要素を取り除くことをお勧めします。次の表に、データを制限して不適切な部分を削除する場合に利用できるオプションをまとめています。
表 10.1: データ要件を制限して不適切な部分を削除するためのオプション
| 型の確認 | .NET Framework 型システム。文字列データの解析、強い型への変換、および
FormatExceptions の処理を行います。 正規表現。ASP.NET
RegularExpressionValidator コントロールまたは Regex クラスを使用します。 |
| 長さの確認 | 正規表現 String.Length プロパティ |
| 形式の確認 | パターン マッチングの正規表現 .NET Framework
型システム |
| 範囲の確認 | ASP.NET RangeValidator コントロール
(通貨、日付、整数、倍精度、および文字列データをサポート) 型指定されたデータの比較 |
正規表現
正規表現を利用すれば、有効な文字の範囲の制限、不要な文字の除去、および長さと形式の確認を実行できます。入力形式を制限するには、入力が一致する必要のあるパターンを定義します。ASP.NET
は RegularExpressionValidator コントロールを提供し、Regex クラスは
System.Text.RegularExpressions 名前空間から利用できます。
検証コントロールを使用する場合は、コントロールが空であれば検証は成功します。必須フィールドの場合は、RequiredFieldValidator
を使用します。また、正規表現の検証の実装は、クライアントとサーバーでわずかに異なります。クライアントでは、Microsoft JScript®
開発ソフトウェアの正規表現構文が使用されます。サーバーでは、System.Text.RegularExpressions.Regex
構文が使用されます。JScript 正規表現構文は System.Text.RegularExpressions.Regex
構文のサブセットなので、クライアントとサーバーの両方で同じ結果になるようにJScript 正規表現構文を使用することをお勧めします。
ASP.NET 検証コントロールの全面的な詳細については、.NET Framework のドキュメントを参照してください。
RegularExpressionValidator コントロール
Web フォーム フィールド入力を検証する場合は、RegularExpressionValidator
コントロールを使用できます。コントロールを Web フォームにドラッグし、その
ValidationExpression、ControlToValidate、ErrorMessage の各プロパティを設定します。
Microsoft Visual Studio® .NET のプロパティ
ウィンドウを使用して検証表現を設定できます。あるいは、Page_Load イベント
ハンドラでプロパティを動的に設定できます。後者の方法では、ページ上のあらゆるコントロールの正規表現をすべてグループ化できます。
Regex クラス
runat="server" プロパティを指定せずに正規の HTML コントロールを使用
(RegularExpressionValidator コントロールは使用禁止) する場合や、他のソース (クエリ文字列、Cookie など)
からの入力を検証する必要がある場合は、個々のアセンブリにおいてページ クラスまたは検証ヘルパー メソッドの Regex
クラスを使用できます。このセクションの後半で、いくつかの例を示します。
正規表現のコメント
次の構文で "#"
を使用して表現の各コンポーネントにコメントを加える場合、正規表現は、非常に簡単に理解できます。コメントを有効にするには、RegexOptions.IgnorePatternWhitespace
の指定も必要です。この指定により、エスケープされていない空白は無視されます。
Regex regex = new Regex(@"
^ # 開始時のアンカー
(?=.*\d) # 1 桁以上が必要
(?=.*[a-z]) # 小文字が 1 文字必要
(?=.*[A-Z]) # 大文字が1 文字必要
.{8,10} # 8 ~ 10 文字の長さ
$ # 終了時のアンカー",
RegexOptions.IgnorePatternWhitespace); 文字列フィールド
文字列フィールド (名前、アドレス、納税者番号など) を検証するには、正規表現を利用して、以下を実行します。
| • | 入力文字の許容範囲を制限します。 |
| • | 書式設定規則を適用します。たとえば、パターンベースのフィールド (納税者番号、郵便番号など)
には、特定のパターンの入力文字が必要です。 |
| • | 長さを確認します。 |
名前
次の例は、名前フィールドの検証に使用する RegularExpressionValidator コントロールを示しています。
<form id="WebForm" method="post" runat="server">
<asp:TextBox id="txtName" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator id="nameRegex" runat="server" ControlToValidate="txtName" ValidationExpression="^[a-zA-Z'.`-´\s]{1,40}$"
ErrorMessage="Invalid name"></asp:RegularExpressionValidator>
</form>
前述の検証表現では、入力名フィールドが英字 (小文字と大文字)、O'Dell のような名前の 1
つのアポストロフィ、およびドット文字に制限されます。さらに、フィールド長が 40 文字に制限されます。
社会保険番号
次の例は、米国の社会保険番号フォーム フィールドの検証に使用されている RegularExpressionValidator
コントロール向けに生成される HTML コードを示しています。
<form id="WebForm" method="post" runat="server">
<asp:TextBox id="txtSSN" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator id="ssnRegex" runat="server" ErrorMessage="Invalid social security number" ValidationExpression="\d{3}-\d{2}-\d{4}"
ControlToValidate="txtSSN"></asp:RegularExpressionValidator>
</form>
前述の検証表現は、Visual Studio .NET に用意されている標準的な表現の 1
つです。この式では、指定された入力フィールドの形式、およびその型と長さが検証されます。入力は、必ず 3 桁の数字とその後にダッシュ、次に 2
桁の数字とその後にダッシュ、さらに 4 桁の数字から成ります。
サーバー コントロール (検証コントロールは禁止) を使用していない場合や、フォーム
フィールド以外のソースからの入力を検証する必要がある場合は、メソッド コードで
System.Text.RegularExpression.Regex クラスを使用できます。次の例は、検証コントロールを使用するのではなく、ページ
クラスで静的 Regex.IsMatch メソッドを直接使用して同じフィールドを検証する方法を示しています。
if (!Regex.IsMatch(txtSSN.Text, @"^\d{3}-\d{2}-\d{4}$"))
{
// 無効な社会保険番号
} 日付フィールド
同じ .NET Framework 型を持つ入力フィールドの型は、.NET Framework
型システムで確認できます。たとえば、日付を検証する場合、入力データに互換性がなければ、次のように入力値を型 System.DateTime
の変数に変換して、その結果の形式例外を処理できます。
try
{
DateTime dt = DateTime.Parse(txtDate.Text).Date;
}
// 型変換が失敗すると、FormatException がスローされます。
catch( FormatException ex )
{
// 無効な日付メッセージを呼び出し側に返します。
}
形式と型の確認のほかに、日付フィールドの範囲の確認を必要とする場合があります。この確認は、次のように DateTime
変数を使用して簡単に実行されます。
// 例外処理は省略
DateTime dt = DateTime.Parse(txtDate.Text).Date;
// 日付は今日以前にする必要があります。
if ( dt > DateTime.Now.Date )
throw new ArgumentException("Date must be in the past"); 数値フィールド
数値データ (有効期間など) を検証する必要がある場合は、int
型を使用して型確認を実行します。文字列入力を整数に変換する場合は、次のように、Int32.Parse または Convert.ToIn32
を使用すれば、無効なデータ型で発生するあらゆる FormatException を処理できます。
try
{
int i = Int32.Parse(txtAge.Text);
. . .
}
catch( FormatException)
{
. . .
} 範囲の確認
場合によっては、入力データが定義済みの範囲に含まれていることを検証する必要があります。次のコードでは、ASP.NET
RangeValidator コントロールを使用して、入力を 0 ~ 255
までの数値に制限しています。この例では、RequiredFieldValidator も使用しています。RequiredFieldValidator
を使用しない場合は、もう一方の検証コントロールは空白入力を受け入れます。
<form id="WebForm3" method="post" runat="server">
<asp:TextBox id="txtNumber" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator id="rangeRegex" runat="server" ErrorMessage="Please enter a number between 0 and 255"
ControlToValidate="txtNumber" style="LEFT:10px; POSITION:absolute; TOP:47px"></asp:RequiredFieldValidator>
<asp:RangeValidator id="RangeValidator1" runat="server" ErrorMessage="Please enter a number between 0 and 255"
ControlToValidate="TextBox1" Type="Integer" MinimumValue="0" MaximumValue="255"
style="LEFT:10px; POSITION:absolute; TOP:47px"></asp:RangeValidator>
<asp:Button id="Button1" style="LEFT:10px; POSITION:absolute; TOP:100px" runat="server" Text="Button"></asp:Button>
</form>
次の例は、Regex クラスを使用して範囲を検証する方法を示しています。
try
{
// 入力が範囲外の場合は例外が発生します。
int i = Convert.ToInt32(sInput);
if ((0 <= i && i <= 255) == true)
{
// データが有効なので、この数値を使用します。
}
}
catch( FormatException )
{
. . .
}
入力の不適切な部分を削除する
不適切な部分を削除するのは、潜在的に悪質なデータを安全にするためです。この機能は、許容入力範囲の確認だけでは入力が安全であることを保証できない場合に役立つ可能性があります。この機能には、ユーザー指定の文字列またはエスケープされた値がリテラルと見なされるように、それらの末尾から
NULL
を除去する機能が含まれています。入力の不適切な部分を削除して特定の入力文字の変換または除去を行う必要がある場合は、Regex.Replace
を使用します。
注: この方法は、多層防御に利用してください。常に、入力を既知の "正常な" 値のセットに制限することから始めます。
次のコードでは、<>\"'%;()& などの潜在的に安全でない各種の文字を取り除いています。
private string SanitizeInput(string input)
{
Regex badCharReplace = new Regex(@"^([<>""'%;()&])$");
string goodChars = badCharReplace.Replace(input, "");
return goodChars;
}
コメント フィールドのような自由形式入力フィールドの不適切な部分を削除する方法の詳細については、このモジュールで後述する「クロスサイト
スクリプティング」の「自由形式入力の不適切な部分を削除する」を参照してください。
HTML コントロールを検証する
サーバー コントロール、つまり runat="server" 属性を持つコントロールを使用せずに、正規の HTML
コントロールを使用する場合は、ASP.NET 検証コントロールを使用できません。代わりに、Web
ページの内容を検証するには、次のように、Page_Load イベント ハンドラで正規表現を利用します。
using System.Text.RegularExpressions;
. . .
private void Page_Load(object sender, System.EventArgs e)
{
// IsPostBack は、runat="server を指定したサーバー フォームです。
// だけに適用される
if ( Request.RequestType == "POST" ) // 非サーバー フォーム
{
// 指定された電子メール アドレスを検証する
if( !Regex.Match(Request.Form["email"],
@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$",
RegexOptions.None).Success)
{
// 無効な電子メール アドレス
}
// 指定された名前を検証します。
if ( !RegEx.Match(Request.Form["name"],
@"^[A-Za-z'\- ]$",
RegexOptions.None).Success)
{
// 無効な名前
}
}
}
データ アクセスに使用される入力を検証する
ユーザー入力に基づいて動的 SQL クエリを生成している場合は、SQL インジェクション攻撃により、データベースで実行できる悪質な SQL
コマンドが注入されるおそれがあります。一般的な Web ベースのデータ アクセス
シナリオでは、以下の多層防御戦略を取り入れることができます。
| • | 正規表現を使用して、ページ クラス内の入力を制限します。 |
| • | 入力の不適切な部分を削除するか、入力を拒否します。多層防御の場合は、ヘルパー メソッドを使用して、NULL
文字または他の既知の不正な文字を除去することも可能です。 |
| • | SQL クエリで使用されるデータに対して型と長さの確認が確実に実行されるように、データ アクセス用のパラメータ化されたストアド
プロシージャを使用します。 |
データ アクセス用のパラメータ、および安全なデータ アクセス コードの作成方法の詳細については、モジュール 14
「セキュリティ保護されたデータ アクセスを構築する」を参照してください。
ファイル I/O に使用される入力を検証する
一般に、呼び出し側からのファイル入力またはパス入力を受け入れるコードは作成しないようにする必要があります。代わりに、データの読み取り時や書き込み時に固定的なファイル名と場所を使用します。このようにすれば、コードから任意のファイルへのアクセスを強制されることはなくなります。また、正規化のバグに対するコードの脆弱性をなくすこともできます。
入力ファイル名を受け入れる必要がある場合は、2 つの大きな課題があります。1 つ目は、受け入れたファイル パスや名前が有効なファイル
システム名になっているかどうかです。2
つ目は、パスがアプリケーションのコンテキストで有効であるかどうかです。たとえば、パスがアプリケーションの仮想ディレクトリ
ルートの下にあるでしょうか。
ファイル名を正規化するには、System.IO.Path.GetFullPath を使用します。ファイル
パスがアプリケーションのコンテキストにおいて有効であることを確認する場合は、.NET コード アクセス
セキュリティを利用して、特定のディレクトリからのファイルだけにアクセスできるようにコードに正確な FileIOPermission
を付与できます。詳細については、モジュール 7 「セキュリティ保護されたアセンブリを構築する」およびモジュール 8「コード アクセス
セキュリティの実践」の「ファイル I/O」を参照してください。
MapPath を使用する
MapPath を使用して指定された仮想パスをサーバー上の物理パスに対応付ける場合は、次のように、クロス アプリケーション
マッピングを防止できるように "ブール" パラメータを受け入れる Request.MapPath のオーバーロードを利用します。
try
{
string mappedPath = Request.MapPath( inputPath.Text,
Request.ApplicationPath, false);
}
catch (HttpException)
{
// クロス アプリケーションマッピングが試行されます。
}
最後の false パラメータによって、クロス アプリケーション
マッピングが防止されます。つまり、ユーザーは、アプリケーションの仮想ディレクトリ階層外に移動するために ".."
を含むパスを指定できないということです。指定しようとしても、型 HttpException の例外が発生します。
注: サーバー コントロールでは、ファイルを読み取るために Control.MapPathSecure
メソッドを使用できます。このメソッドでは、コード アクセス セキュリティ
ポリシーによって呼び出し側のコードが完全に信頼できる状態でなければなりません。そうでなければ、HttpException
がスローされます。詳細については、.NET Framework SDK
ドキュメントの「Control.MapPathSecure」を参照してください。
一般的な正規表現
Visual Studio .NET
には、実用的な特定の正規表現が用意されています。こうした正規表現にアクセスするには、RegularExpresssionValidator
コントロールを Web フォームに追加し、コントロールの "式" プロパティ フィールドの省略ボタンをクリックします。次の表は、一般に Web
ページ フィールドに使用される、さらに実用的な表現をいくつか示しています。
表 10.2: 実用的な正規表現フィールド
| 名前 | [a-zA-Z'`-´\s]{1,40} | John DoeO'Dell | 名前を検証します。大文字と小文字、および名前によく使われるいくつかの特殊文字を 40
文字まで使用できます。このリストは変更できます。 |
| 数字 | ^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$ | (425)-555-0123 425-555-0123 425 555
0123 | 米国の電話番号を検証します。 |
| 電子メール | \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* | mailto:test@test.com | 電子メール アドレスを検証します。 |
| URL | ^(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~])*$ | | URL を検証します。 |
| 郵便番号 | ^(\d{5}-\d{4}|\d{5}|\d{9})$|^([a-zA-Z]\d[a-zA-Z]
\d[a-zA-Z]\d)$ | | 米国の 5 桁または 9 桁の郵便番号を検証します。 |
| パスワード | ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$ | | 強固なパスワードを検証します。8 ~ 10
文字を指定する必要があります。特殊文字は使用せずに、大文字、小文字、および数字を組み合わせる必要があります。 |
| 非負整数 | \d+ | 0986 | 0 より大きい整数を検証します。 |
| 通貨 (0 以上) | "\d+(\.\d\d)?" | | 正の貨幣額を検証します。小数点以下 2 桁を必要とします。 |
| 通貨 (正または負) | "(-)?\d+(\.\d\d)?" | | 正または負の貨幣額を検証します。小数点以下 2
桁を必要とします。 |
クロスサイト スクリプティング
XSS 攻撃では、Web ページ検証の脆弱性を悪用するために、クライアント側のスクリプト
コードが注入されます。その後、このコードは疑いを持たないユーザーに返送され、ブラウザで実行されます。ブラウザは、信頼できるサイトからスクリプト
コードをダウンロードするため、コードが正当でないことを識別する方法がブラウザに用意されておらず、Internet Explorer のセキュリティ
ゾーンでは防御できません。XSS 攻撃は、HTTP または HTTPS (SSL)
接続でも機能します。最も深刻な脆弱性が検出されるのは、攻撃者が信頼できるサイトへのアクセスを提供する認証 Cookie
を取得するスクリプトを作成し、それを攻撃者が知っている Web
アドレスに送信する場合です。この脆弱性により、攻撃者は、正当なユーザーの識別情報を偽装して Web サイトに不法にアクセスできます。
XSS 攻撃を防ぐには、以下の対策を実施してください。
入力を検証する
このモジュールで以前に説明した各種テクノロジを駆使して型、長さ、形式、範囲について、アプリケーションの信頼境界外から受信するあらゆる入力を検証します。
出力をエンコードする
テキスト出力を Web ページに書き込み、そのテキストに HTML 特殊文字 (<、>、& など)
が含まれていないことがはっきりしない場合は、HttpUtility.HtmlEncode
メソッドを使用してそのテキストを必ず前処理してください。ユーザー入力、データベース、またはローカル
ファイルからのテキストであっても、この作業を行ってください。同様に、HttpUtility.UrlEncode を使用して URL
文字列をエンコードします。
HtmlEncode メソッドは、HTML で特殊な意味を持つ文字をそれぞれの文字を表す HTML 変数に置換します。たとえば、< は
< に置き換えられ、" は "
に置き換えられます。データをエンコードしておけば、ブラウザでコードとして実行されることはありません。代わりに、そのデータは害のない HTML
として表示されます。
Response.Write(HttpUtility.HtmlEncode(Request.Form["name"]));
データ連結コントロール
データ連結 Web コントロールでは、出力をエンコードしません。出力をエンコードする唯一のコントロールは TextBox
コントロールで、しかもその TextMode プロパティが MultiLine に設定されている場合です。他のコントロールを悪質な XSS
コードを持つデータにバインドすると、そのコードはクライアントで実行されます。その結果、データベースからデータを取得し、おそらくデータベースが他のアプリケーションと共有されているためにデータが有効であることがはっきりしない場合は、そのデータをクライアントに渡す前にデータをエンコードしてください。
自由形式入力の不適切な部分を削除する
Web ページに自由形式のテキスト ボックス ("コメント" フィールドなど) が含まれており、そこに特定の安全な HTML 要素
(<b>、<i> など) を許可したい場合、この処理を正しく行うには、次のように、最初に HtmlEncode
で前処理した後、許可されている要素のエンコードを部分的に削除します。
StringBuilder sb = new StringBuilder( HttpUtility.HtmlEncode(userInput) ) ;
sb.Replace("<b>", "<b>");
sb.Replace("</b>", "</b>");
sb.Replace("<i>", "<i>");
sb.Replace("</i>", "</I>");
Response.Write(sb.ToString());
多層防御対策
既に説明した技法のほかに、以下の多層防御向け対策によって XSS を防止します。
| • | 正しい文字エンコードを設定します。 |
| • | ASP.NET バージョン 1.1 の validateRequest オプションを使用します。 |
| • | URLScan を Web サーバーにインストールします。 |
| • | HttpOnly Cookie オプションを使用します。 |
| • | <frame> セキュリティ属性を使用します。 |
| • | innerText プロパティを使用します。 |
正しい文字エンコードを設定する
Web
ページに対して有効なデータを正しく制限するには、入力データの表現方法を制限することが重要です。このようにすれば、悪質なユーザーは、正規化およびマルチバイト
エスケープ シーケンスを使用して入力検証ルーチンに仕掛けを施すことができなくなります。
ASP.NET では、Web.config で <globalization> 要素を使用することにより、ページ レベルまたは
アプリケーション レベルで文字セットを指定できます。この 2 つの方法を、ISO-8859-1
文字エンコードを使用して以下に示します。このエンコードは、HTML と HTTP の初期バージョンの既定値です。
ページ レベルで文字エンコードを設定するには、次のように <meta> 要素または ResponseEncoding ページ
レベル属性を使用します。
<meta http-equiv="Content Type"
content="text/html; charset=ISO-8859-1" />
または
<% @ Page ResponseEncoding="ISO-8859-1" %>
Web.config で文字エンコードを設定するには、次の構成を使用します。
<configuration>
<system.web>
<globalization requestEncoding="ISO-8859-1" responseEncoding="ISO-8859-1" />
</system.web>
</configuration>
Unicode 文字を検証する
ページ内の Unicode 文字を検証するには、次のコードを使用します。
using System.Text.RegularExpressions;
. . .
private void Page_Load(object sender, System.EventArgs e)
{
// 名前には、1 ~ 40 桁の英数字、および
// 必要に応じて D'Angelo のような名前に対する
// 特殊文字 '`´ を指定します。
if (!Regex.IsMatch(Request.Form["name"], @"^[\p{L}\p{Zs}\p{Lu}\p{Ll}]{1,40}$"))
throw new ArgumentException("Invalid name parameter");
// 個別に正規表現を利用して他のパラメータを検証します。
. . .
}
以下に、前出のコードで使用されている正規表現を説明します。
| • | {<name>}: 指定された Unicode 文字クラスを示します。 |
| • | \p{<name>}: {<name>}
の示す指定された文字クラスの任意の文字に対応します。 |
| • | {L}: 左から右に検出を実行します。 |
| • | {Lu}: 大文字の検出を実行します。 |
| • | {Ll}: 小文字の検出を実行します。 |
| • | {Zs}: 区切り文字と空白文字を検出します。 |
| • | {1,40}: 1 ~ 40 文字までを表します。 |
| • | {Mn}: 記号および空白でない文字を検出します。 |
| • | {Zs}: 区切り文字と空白文字を検出します。 |
| • | *: 0 文字以上の検出を示します。 |
| • | $: この位置で参照を終了することを表します。 |
ASP.NET validateRequest オプションを使用する
validateRequest 属性は、.NET Framework バージョン 1.1 の機能です。この属性は、Machine.config
における <pages> 要素の既定値によって True に設定されます。この設定により、ASP.NET
で、ブラウザから受信したすべてのデータに悪質な入力 (<script> 要素を含む入力など)
が含まれていないか調査されます。ASP.NET では、HTML フォーム
フィールド、Cookie、およびクエリ文字列から受信した入力が調べられます。.NET Framework バージョン 1.0
には同等の機能はありませんが、IIS URLScan ISAPI (Internet Server Application Programming
Interface) フィルタで類似ジョブを実行できます。また、次のように、@ Page
タグを使用して設定を各ページに適用することもできます。
<% @ Page validateRequest="True" %>
URLScan を Web サーバーにインストールする
URLScan は、IISLockdown ツールを実行するときにインストールされる ISAPI
フィルタです。このフィルタは、潜在的に悪質な入力を拒否することで XSS 攻撃の脅威を軽減するのに役立ちます。IISLockdown と
URLScan の詳細については、モジュール 16 「Web サーバーをセキュリティ保護する」を参照してください。
注: Windows Server 2003 の IIS 6.0 には、組み込みの URLScan
に相当する機能が用意されています。
HttpOnly Cookie オプションを使用する
Internet Explorer 6 Service Pack 1 は新しい HttpOnly Cookie
属性をサポートします。この属性により、クライアント側スクリプトで document.cookie プロパティから Cookie
にアクセスできなくなります。代わりに、空の文字列が返されます。ただし、ユーザーが現在のドメインの Web サイトを参照するときは必ず、これまでどおり
Cookie がサーバーに送信されます。
注: HttpOnly Cookie 属性をサポートしていない Web ブラウザは、Cookie
を無視するか、属性を無視します。つまり、依然として XSS 攻撃を受けるおそれがあるということです。
System.Net.Cookie クラスは、現在 HttpOnly プロパティをサポートしていません。Cookie HttpOnly
属性を追加するには、ISAPI フィルタを使用する必要があります。あるいは、マネージ コード ソリューションが必要な場合は、Global.asax
でアプリケーションの Application_EndRequest イベント ハンドラに次のコードを追加します。
protected void Application_EndRequest(Object sender, EventArgs e)
{
string authCookie = FormsAuthentication.FormsCookieName;
foreach (string sCookie in Response.Cookies)
{
// フォーム認証 Cookie に HttpOnly 属性を設定します。
// コレクション内のすべての Cookie に属性を設定するために、この確認をスキップします。
if (sCookie.Equals(authCookie))
{
// HttpOnly をCookie ヘッダーに強制的に追加します。
Response.Cookies[sCookie].Path += ";HttpOnly";
}
}
}
注: .NET Framework の今後のバージョンでは、Cookie クラスに HttpOnly
プロパティを装備する可能性があります。
<frame> セキュリティ属性を使用する
Internet Explorer 6 以降では、<frame> と <iframe> の要素に対する
security 属性を新たにサポートします。この security 属性を使用すれば、ユーザーの Internet Explorer
の制限付きサイト セキュリティ ゾーン設定を個々の frame または iframe
に適用できます。既定では、制限付きサイトゾーンは、スクリプト実行をサポートしていません。security 属性を使用する場合は、以下に示すように
"restricted" に設定する必要があります。
<frame security="restricted" src="http://www.somesite.com/somepage.htm"></frame>
innerText プロパティを使用する
信頼されていない入力でページを作成する場合は、innerHTML ではなく innerText プロパティを使用します。innerText
プロパティは、コンテンツを安全にし、スクリプトが実行されないようにします。
認証
認証が脆弱な場合は、なりすましの脅威が高まります。ユーザーのログオン資格情報が攻撃者に渡ると、攻撃者は、ユーザーの識別情報を偽装してアプリケーションにアクセスできるようになります。攻撃者は、そのアプリケーションでユーザーのすべての特権を共有します。資格情報は、ネットワーク経由で渡されるときやアプリケーションのユーザー
ストアなどに保持されている間、保護されている必要があります。最初のログオン後にアプリケーションに対する認証済み識別情報を表す認証 Cookie
も、セッション ハイジャックや Cookie リプレイ攻撃のリスクを軽減するために保護されている必要があります。
フォーム認証
フォーム認証を利用するアプリケーションには、セッション ハイジャックと Cookie リプレイ攻撃の脅威は特に重要です。SQL
インジェクションに対して脆弱にならないようにユーザー指定の資格情報を使用してデータベースを照会する場合は、特に注意を払う必要があります。さらに、なりすましを防ぐために、ユーザー
ストアがセキュリティ保護されており、強固なパスワードが設定されていることを確認する必要があります。
次のコードは、Web.config での "セキュリティ保護された" フォーム認証構成を示しています。
<forms loginUrl="Restricted\login.aspx" SSL で保護されたフォルダ内のログイン ページ
protection="All" プライバシーと整合性
requireSSL="true" http で Cookie を送信しないようにする
timeout="10" セッション有効期間の制限
name="AppNameCookie" アプリケーションごとの一意な名前
path="/FormsAuth" およびパス
slidingExpiration="true" > セッション有効期間を変更する
</forms>
以下の推奨事項は、セキュリティ保護されたフォーム認証ソリューションを構築するのに役立ちます。
| • | Web サイトを分割します。 |
| • | 制限されたページを SSL でセキュリティ保護します。 |
| • | URL 認証を利用します。 |
| • | 認証 Cookie をセキュリティ保護します。 |
| • | 移動に絶対 URL を使用します。 |
| • | セキュリティ保護された資格情報管理を利用します。 |
Web サイトを分割する
サイト設計で、認証済みアクセスを必要とするセキュリティ保護されたページが、匿名でアクセスできるページとは別のサブディレクトリに格納されていることを確認します。図
10.3 は、Visual Studio .NET ソリューション エクスプローラ ウィンドウでの一般的な配列を示しています。フォーム ログイン
ページが、別々のサブディレクトリにある他の制限されたページと共に格納されていることに注意してください。
図 10.3
認証済みアクセスを必要とする制限されたページ用のサブディレクトリ
注: 匿名ページからセキュリティ保護されたページに転送するためにアプリケーションで Server.Transfer
を使用している場合、.NET Framework バージョン 1.1 以前では、認証検査を回避するので、Server.Transfer
を使用するコードでセキュリティ保護されたディレクトリに転送していないことを確認する必要があります。
制限されたページを SSL でセキュリティ保護する
SSL を利用してログイン フォームから送信されるログオン資格情報を確実に保護し、制限されたページに対する以降の要求に認証 Cookie
を確実に渡すために、SSL を要求するように IIS のセキュリティ保護されたフォルダを構成します。これにより、IIS メタベースにおいてフォルダの
AccessSSL=true 属性が設定されます。要求 URL で https
が使用されている場合に限り、セキュリティ保護されたフォルダ内のページの要求が成功します。
SSL の場合は、サーバー証明書が Web サーバーにインストールされている必要があります。詳細については、Microsoft
patterns & practices「セキュリティ保護された ASP.NET アプリケーションの構築:
認証、認定、および通信のセキュリティ保護」の「Web サーバー上で SSL を設定する方法」(http://www.microsoft.com/japan/msdn/net/security/SecNetHT16.asp)
を参照してください。
URL 認証を利用する
公開ページへの匿名アクセスを許可するには、次の <authorization> 要素を使用します。
<system.web>
<!-- 仮想ディレクトリ ルート フォルダには一般的なページが格納されています。
認証されていないユーザーは一般的なページを表示できますが、
それを SSL でセキュリティ保護する必要はありません。 -->
<authorization>
<allow users="*" />
</authorization>
</system.web>
Web.config の <location> 要素において次の <authorization>
要素を使用して、認証されていないユーザーのアクセスを拒否し、<forms> 要素で指定されたログイン
ページに強制的にリダイレクトします。
<!-- 制限されたフォルダは、認証済みアクセスと SSL アクセス専用です。 -->
<location path="Secure">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
認証 Cookie をセキュリティ保護す