エクスポート (0) 印刷
すべて展開

コード レビュー

 

公開日: 2004年9月7日 | 最終更新日: 2004年9月7日
トピック
モジュールの内容 モジュールの内容
目的 目的
適用対象 適用対象
モジュールの使用方法 モジュールの使用方法
FxCop FxCop
テキスト検索の実行 テキスト検索の実行
クロスサイト スクリプティング (XSS) クロスサイト スクリプティング (XSS)
SQL インジェクション SQL インジェクション
バッファ オーバーフロー バッファ オーバーフロー
マネージ コード マネージ コード
コード アクセス セキュリティ コード アクセス セキュリティ
アンマネージ コード アンマネージ コード
ASP.NET のページおよびコントロール ASP.NET のページおよびコントロール
Web サービス Web サービス
サービス対象のコンポーネント サービス対象のコンポーネント
Remoting Remoting
データ アクセス コード データ アクセス コード
要約 要約
関連情報 関連情報

モジュールの内容

セキュリティ コード レビューは、セキュリティ問題およびインシデントの原因となりうるセキュリティで保護されていないコーディングや脆弱性の識別に重点を置きます。コード レビューには時間がかかりますが、開発段階でセキュリティの短所修正に要する労力およびコストは、その後の製品展開や保守サイクルで要する労力およびコストに比べてはるかに少ないため、プロジェクト開発サイクルの定期的なイベントとして行う必要があります。

このモジュールは、Microsoft® .NET Framework を使用して構築された ASP.NET Web アプリケーション コードをレビューするうえで役立ちます。このモジュールは機能別に構成されています。また、コード レビュー プロセスの手法およびフレームワークを把握するうえで役立つ、包括的なレビュー項目リストを含むセクションも用意されています。

目的

このモジュールの目的は次のとおりです。

コード レビューと ASP.NET セキュリティ監査を行うための手法およびフレームワークを作成する。

クロスサイト スクリプティングに対して脆弱な箇所を見つけ出す。

SQL インジェクションに対して脆弱な箇所を見つけ出す。

バッファ オーバーランする可能性のある箇所を見つけ出す。

セキュリティに関する包括的な確認項目一覧の各項目について確認し、セキュリティの問題を迅速に特定する。

個別の .NET Framework 技術に固有のセキュリティ問題を評価する。

悪意のあるユーザーから攻撃を受けやすいコーディング技法を識別する。

ソース コードおよび利用可能な .NET アセンブリを分析するため、FxCop、テキスト検索、およびILDASM の使用法を把握する。

適用対象

このモジュールは、次の製品およびテクノロジに適用されます。

Microsoft Windows® 2000 Server および Windows Server™ 2003

Microsoft .NET Framework 1.1 および ASP.NET 1.1

Microsoft SQL Server 2000

モジュールの使用方法

このモジュールを使用して、コード レビュー プロセスを作成、または既存のコード レビュー プロセスを拡張します。コード レビューが開発サイクルの一部として組み込まれていることを確認し、その効果は割り当てられたリソースと予算の量に応じたものであることを認識しておく必要があります。

レビューの目標は、コードを展開する前にできるだけ多くのセキュリティの脆弱性を識別することです。開発段階でセキュリティの短所修正に要する労力およびコストは、その後の製品展開サイクルで要する労力やコストに比べてはるかに少ないからです。

このモジュールから最大限の成果を得るための参考資料は、次のとおりです。

このガイドの第 3 部のセキュリティ保護に関するモジュールを使用します。このモジュールで概説するレビュー項目の詳細については、これらのモジュールを参照してください。

モジュール 6「.NET セキュリティの概要」

モジュール 7「セキュリティ保護されたアセンブリを構築する」

モジュール 8「コード アクセス セキュリティの実践」

モジュール 9「ASP.NET でコード アクセス セキュリティを使用する」

モジュール 10「セキュリティ保護された ASP.NET ページとコントロールを構築する」

モジュール 11「セキュリティ保護されたサービス コンポーネントを構築する」

モジュール 12「セキュリティ保護された Web サービスを構築する」

モジュール 13「セキュリティ保護されたリモート コンポーネントを構築する」

モジュール 14「セキュリティ保護されたデータ アクセスを構築する」

次の関連チェックリストも使用します。

チェックリスト: アーキテクチャと設計レビュー

チェックリスト: ASP.NET をセキュリティ保護する

チェックリスト: Web サービスをセキュリティ保護する

チェックリスト: Enterprise Services をセキュリティ保護する

チェックリスト: Remoting をセキュリティ保護する

チェックリスト: データ アクセスをセキュリティ保護する

FxCop

レビュー プロセスを始めるにあたって、まずコンパイル済みのアセンブリを FxCop 分析ツールにかけることをお勧めします。このツールを使用してバイナリ アセンブリ (ソース コードではありません) を分析し、それらが MSDNで入手可能な「.NET Framework Design Guidelines」(英語) に準拠していることを確認することができます。強固な名前がアセンブリに付けられていることも、このツールで確認されます。強固な名前には不正操作を防ぐなどのセキュリティ上の利点があります。このツールにはあらかじめルールが定義されていますが、ルールをカスタマイズまたは拡張することもできます。

詳細については、以下のリソースを参照してください。

FxCop ツールのダウンロードについては、http://www.gotdotnet.com/team/libraries/default.aspx (英語) を参照してください。

FxCop ツールのヘルプおよびサポートについては、http://www.gotdotnet.com/community/messageboard/MessageBoard.aspx?ID=234 (英語) を参照してください。

FxCop がチェック時に適用するセキュリティ規則のリストについては、http://www.gotdotnet.com/team/libraries/FxCopRules/SecurityRules.aspx (英語) を参照してください。

「.NET Framework Design Guidelines」 については、http://www.microsoft.com/japan/msdn/library/ja/cpgenref/html/cpconnetframeworkdesignguidelines.asp を参照してください。

テキスト検索の実行

レビュー プロセスに使用するため、ファイル内の文字列を検索するテキスト検索ツールの使用法を知っていることが必要です。この種のツールを使用すると、脆弱なコードをすばやく検索することができます。このモジュールのレビュー項目では、特定の脆弱性の検索に最も適した文字列が多く示されています。

既存の検索ツールを使用していらっしゃると思いますが、Visual Studio® .NET の Find in Files、または Microsoft Windows オペレーティング システムのコマンド ライン ツールである Findstr も使用できます。

注: エクスプローラから Windows XP 検索ツールの [ファイルに含まれる単語または句] オプションを使用する場合、最新の Windows XP の Service Pack がインストールされていることを確認してください。インストールされていないと、検索に失敗する可能性があります。詳細については、マイクロソフト サポート技術情報の 309173「"ファイルに含まれる単語または句" 検索条件が機能しない」を参照してください。

ハード コード文字列の検索

ソース コードを 1 行ずつ詳細に分析する前にコード全体を高速検索し、ハード コードされたパスワード、アカウント名、データベースの接続文字列を特定します。key、secret、password、pwd、および connectionstring のような一般的な文字列パターンについて、コードの検索を行います。
たとえば、アプリケーションの Web ディレクトリで password という文字列を検索する場合は、次のように、コマンド プロンプトで Findstr ツールを使用します。

findstr /S /M /I /d:c:\projects\yourweb "password" *.*

Findstr では、以下のコマンド ライン パラメータを使用します。

/S — サブディレクトリも検索します。

/M — ファイル名のみを出力します。

/I — 大文字と小文字を区別しません。

/D:dir — セミコロンで区切られたディレクトリの一覧を検索します。検索するファイル パスにスペースが含まれる場合は、パスを二重引用符で囲みます。

Findstr の自動化

一般的な検索文字列を含むテキスト ファイルを作成することもできます。以下に示すように、Findstr を使用して作成されたテキスト ファイルから文字列を読み込み、検索することができます。.apsx ファイルを含むディレクトリから以下のコマンドを実行します。

findstr /N /G:SearchStrings.txt *.aspx

/N は一致する各行の前に行番号を出力します。/G は検索文字列を含むファイルを示します。この例では、SearchStrings.txt に含まれるすべての文字列の検索がASP.NET の全ページ (*.aspx) で行われます。

ILDASM

Findstr コマンドと ildasm.exe ユーティリティを組み合わせると、ハード コード文字列のバイナリ アセンブリを検索することもできます。以下のコマンドでは、ildasm.exe を使用して ldstr 中間言語ステートメントを検索し、文字列定数を識別しています。以下の出力結果が、ハード コードされたデータベース接続、およびよく知られている SA アカウントのパスワードを示していることに注目してください。

Ildasm.exe secureapp.dll /text | findstr ldstr
IL_000c:  ldstr      "RegisterUser"
IL_0027:  ldstr      "@userName"
IL_0046:  ldstr      "@passwordHash"
IL_0065:  ldstr      "@salt"
IL_008b:  ldstr      "Exception adding account. "
IL_000e:  ldstr      "LookupUser"
IL_0027:  ldstr      "@userName"
IL_007d:  ldstr      "SHA1"
IL_0097:  ldstr      "Exeception verifying password. "
IL_0009:  ldstr      "SHA1"
IL_003e:  ldstr      "Logon successful: User is authenticated"
IL_0050:  ldstr      "Invalid username or password"
IL_0001:  ldstr      "Server=AppServer;database=users; username='sa'   
password=password"

注: Ildasm.exe は、\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin フォルダに保存されています。サポートされるコマンド ラインの詳細については、「ildasm.exe /?」を実行してヘルプを参照してください。

クロスサイト スクリプティング (XSS)

入力パラメータがクライアントへ戻る出力 HTML ストリームに使用されている場合、コードのその箇所はどこもクロスサイト スクリプティング (XSS、または CSS とも呼ばれます) 攻撃に対して脆弱です。アプリケーションが XSS に対して脆弱かどうかは、コード レビュー前でも簡単にテストできます。ユーザー入力情報がブラウザに返されるページを検索してください。

XSS バグは、ユーザーが入力したデータを信頼しすぎるために生じる問題の一例です。たとえば、ユーザーが価格を入力することになっているアプリケーションに、攻撃者は価格だけでなく HTML と JavaScript を入力します。したがって、信頼関係にないソースから入力されたデータは、必ず検証することが必要です。コード レビューでは、データが検証済みかどうかを常に確認してください。HTTP ヘッダ、クエリ文字列、フォーム データなど ASP.NET アプリケーションのすべてのエントリ ポイントをリストし、すべての入力がどこかのポイントで必ず検証されるようにします。このアプローチでは潜在的に危険な入力はすべて把握されていることを前提としているため、不正な入力値かどうかはテストしないてください。データが ASP.NET アプリケーションで有効であることの確認に、正規表現を使用した方法が最も一般的に用いられます。

フォーム フィールドに XYZ などの文字列を入力して出力させるだけで簡単にテストできます。ブラウザに "XYZ" と表示される、または HTML のソースに "XYZ" が含まれる場合、その Web アプリケーションは XSS に対して脆弱です。より動的に確認する場合は、「<script>alert('hello');</script>」を挿入します。この手法は入力が出力生成にどのように利用されるかに依存しているため、すべての場合に有効な訳ではありません。

次の手順は、一般的な XSS に対する脆弱性を確認するうえで役立ちます。

入力を出力するコードの識別

潜在的に危険な HTML タグおよび属性の識別

URL を処理するコードの識別

出力がエンコードされていることの確認

文字のエンコードが正しいかどうかの確認

validateRequest 属性の確認

HttpOnly Cookie オプションの確認

<frame> セキュリティ属性の確認

innerText および innerHTML プロパティの使用の確認

入力を出力するコードの識別

ブラウザからページの出力ソースを表示させ、属性の中にコードが入っているかどうかを確認します。入っている場合、以下のコードを挿入して出力表示を再び確認します。

"onmouseover= alert('hello');"

開発者によく用いられる手法が、「<」および「>」の文字をフィルタすることです。レビューしているコードがこれらの文字をフィルタする場合、次に以下のコードを使用してテストします。

&{alert('hello');}

コードがこれらの文字をフィルタしない場合、以下のスクリプトを使用してコードをテストします。

<script>alert(document.cookie);</script>;

以下に示すように、タグを閉じてからでないと、このスクリプトが使用できない場合もあります。

"></a><script>alert(document.cookie);</script>

Write の検索

.aspx ソース コードおよびアプリケーションで開発したすべての関連アセンブリに含まれるコードで、文字列 .Write を検索します。この検索により、Response.Write、および以下に示すような Response オブジェクト変数を介して出力を生成する内部ルーチンを確認できます。

public void WriteOutput(Response respObj)
{
respObj.Write(Request.Form["someField"]);
}

以下に示すように、.aspx ソース コードを、同じように出力の書き込みに用いられる文字列 "<%=" で検索する必要があります。

<%=myVariable %>

表 21.1 に、Response.Write が入力フィールドとともに使用される一般的な状況を示します。

表 21.1: 考えられる入力ソース

入力ソース

フォーム フィールド

 Response.Write(name.Text);
Response.Write(Request.Form["name"]); 

クエリ文字列

 Response.Write(Request.QueryString["name"]); 

Cookie

Response.Write(  
Request.Cookies["name"].Values["name"]);

セッションおよびアプリケーション変数

Response.Write(Session["name"]);
Response.Write(Application["name"]);

データベースおよびデータ ストア

SqlDataReader reader = cmd.ExecuteReader();
Response.Write(reader.GetString(1));

潜在的に危険な HTML タグおよび属性の識別

以下は、完全には網羅していませんが、悪意のあるユーザーがスクリプト コードの挿入に使用する可能性がある一般的な HTML タグです。

<applet>

<body>

<embed>

<frame>

<script>

<frameset>

<html>

<iframe>

<img>

<style>

<layer>

<ilayer>

<meta>

<object>

src、lowsrc、style、href などの HTML 属性は、これらのタグと組み合わせて XSS を引き起こす際に使用される可能性があります。

たとえば、<img> タグの src 属性は、以下の例に示すように挿入のソースとなることがあります。

<IMG SRC="javascript:alert('hello');">
<IMG SRC="java&#010;script:alert('hello');">
						<IMG SRC="java&#X0A;script:alert('hello');">

<style> タグも、以下に示すように MIME タイプを変更させることにより、挿入のソースとなることがあります。

<style TYPE="text/javascript">
alert('hello');
</style>

危険なことが分かっている文字をフィルタして、コードが入力のサニタイジングを試みるかどうかを確認します。一般的に、悪意のあるユーザーは検証をバイパスできる別の表記を見つけるため、このアプローチに依存しないでください。このアプローチに依存する代わりに、セキュリティで保護された安全な既知の入力をコードが検証できるようにする必要があります。表 21.2 に、一般的な文字を表記するさまざまな方法が示されています。

表 21.2: 文字表記

文字 10 進 16 進 HTML 文字セット Unicode

" (二重引用符)

 
&#34;

&#x22;

 &quot;

\u0022

' (一重引用符)

&#39;

&#x27;

&apos;

\u0027

& (アンパサンド)

&#38;

&#x26

&#38;

\u0026

< (小なり)

&#60

&#x3C;

&#60;

\u003c

> (大なり)

&#62

&#x3E;

&#62;

\u003e

URL を処理するコードの識別

URL を処理するコードが脆弱な場合があります。次のような一般的な攻撃に対して脆弱かどうかについて、コードをレビューしてください。

Web サーバーが最新のセキュリティ パッチで更新されていない場合、以下のディレクトリ トラバーサルおよびダブル スラッシュ攻撃に対して脆弱である可能性があります。

http://www.YourWebServer.com/..%255%../winnt
http://www.YourWebServer.com/..%255%..//somedirectory

コードが "/" をフィルタする場合も、攻撃者は同じ文字に別の表記を用いることにより、簡単にフィルタを回避してしまいます。たとえば、"/" の UTF–8 表記は "%c0f%af" ですが、これを次のように URL で使用することができます。

http://www.YourWebServer.com/..%c0f%af../winnt

クエリ文字列入力を処理する場合、コードが入力データを制限して範囲チェックを行うことを確認します。攻撃者からクエリ文字列のパラメータを使った非常に大きいデータが渡された場合にも、コードが脆弱でないことを確認してください。

http://www. WebServer.com/test.aspx?var=ここに非常に大きなデータを挿入する

出力がエンコードされていることの確認

入力のフォームおよび内容が正しいことを確認する代わりにはなりませんが、すべての入力タイプを含む HTML 出力が、HtmlEncode を使用してエンコードされていることを確認する必要があります。URL 文字列が UrlEncode を使用してエンコードされていないことも確認してください。入力データは、クエリ文字列、フォーム データ、Cookie、HTTP ヘッダ、および、特にデータベースが他のアプリケーションと共有されている場合はデータベースの読み込み値である可能性があります。データをエンコードすることにより、ブラウザが HTML を実行可能なスクリプトとして利用するのを防ぐことができます。

文字のエンコードが正しいかどうかの確認

文字エンコードが入力の表記方法を正しく制限する設定になっていることを確認して、正規化およびマルチバイトのエスケープ文字列を使用する攻撃者により、入力検証ルーチンが欺かれるのを防ぎます。

アプリケーションの Web config ファイルが、以下に示す <globalization> 要素で構成される requestEncoding および responseEncoding 属性を持つことを確認します。

<configuration>
<system.web>
						<globalization requestEncoding="ISO-8859-1" responseEncoding="ISO-8859-1" />
					</system.web>
</configuration>

文字エンコードは、<meta> タグまたは以下に示すように ResponseEncoding ページ レベル属性を使用して、ページ レベルで設定することもできます。

<% @ Page ResponseEncoding="ISO-8859-1" %>

詳細については、モジュール 10「セキュリティ保護された ASP.NET ページとコントロールを構築する」を参照してください。

validateRequest 属性の確認

.NET Framework version 1.1 を使用して構築された Web アプリケーションでは、埋め込みスクリプトのような潜在的に悪意のある入力を取り除くため、入力のフィルタ処理を行います。この処理に依存することはできませんが、重層的な防御のために使用してください。構成ファイルの <pages>要素で、validateRequest属性が true に設定されていることを確認します。この属性もページ レベルで設定することができます。.aspx ソース ファイルを validateRequest で検索して、どのページも false に設定されていないことを確認します。

HttpOnly Cookie オプションの確認

Internet Explorer 6 SP 1 は、クライアントのスクリプトが document.cookie プロパティから Cookie へアクセスすることを阻止する、新しい HttpOnly Cookie 属性をサポートしています。読み込もうとすると、空文字列が戻されます。ユーザーが現在のドメインで Web サイトを参照する場合は、Cookie はこれまでと同様にサーバーに送信されます。詳細については、モジュール 10「セキュリティ保護された ASP.NET ページとコントロールを構築する」の「クロスサイト スクリプティング」を参照してください。

<frame> セキュリティ属性の確認

Internet Explorer 6 以降では、<frame> および <iframe> 要素での新しい security 属性がサポートされています。この security 属性を使用して、ユーザーの Internet Explorer のセキュリティ ゾーンの制限付きサイト設定を各 frame または iframe に適用することができます。詳細については、モジュール 10「セキュリティ保護された ASP.NET ページとコントロールを構築する」の「クロスサイト スクリプティング」を参照してください。

innerText および innerHTML プロパティの使用の確認

信頼できない入力が含まれるページを作成した場合、innerHTML プロパティの代わりに innerText プロパティを使用していることを確認します。innerText プロパティを使用すると、コンテンツが安全に表示され、スクリプトが実行されないことが確実になります。

関連情報

XSS の詳細については、以下の資料を参照してください。

クイック スタート : クロスサイト スクリプティングに対する自衛策

CSS Overview」(英語)

マイクロソフト サポート技術情報の 252985「[ASP] HOWTO: クロスサイト スクリプティングの脆弱性の問題

CERT/CC Web サイトの「CERT Advisory CA–2000–02, Malicious HTML Tags Embedded in Client Web Requests」(英語)

CERT/CC Web サイトの「Understanding Malicious Content Mitigation for Web Developers」(英語)

SQL インジェクション

入力パラメータを使用して SQL ステートメントを構築している箇所はすべて、SQL インジェクション攻撃に対し脆弱です。XSS バグと同様に、SQL インジェクション攻撃は、ユーザーからの入力を信頼してその入力の内容とフォームが正しいことを検証しないことが原因です。

以下の手順は、SQL インジェクション攻撃に対する脆弱性を確認するうえで役立ちます。

1.

データベースにアクセスするコードを確認します。
文字列「SqlCommand」、「OleDbCommand」、または「OdbcCommand」で検索します。

2.

コードにパラメータ化ストアド プロシージャが使用されているかどうかを確認します。
ストアド プロシージャだけでは SQL インジェクション攻撃を防ぐことはできません。コードにパラメータ化ストアド プロシージャが使用されていることを確認してください。SqlParameter、OleDbParameter、OdbcParameter などの型付けされたパラメータ オブジェクトがコードに使用されていることを確認します。以下に、SqlParameter を使用した例を示します。

SqlDataAdapter myCommand = new SqlDataAdapter("spLogin", conn);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter parm = myCommand.SelectCommand.Parameters.Add(
"@userName", SqlDbType.VarChar,12);
parm.Value=txtUid.Text;

型付けされた SQL パラメータは、入力データの型および長さをチェックして、その userName 入力がデータベースで実行可能なコードではなく、リテラルな文字であることを確認します。

3.

コードに SQL ステートメントのパラメータが使用されていることを確認します。
ストアド プロシージャを使用しない場合、コードが構築した SQL ステートメントに、パラメータが使用されていることを確認します。次にその例を示します。

select status from Users where UserName=@userName

以下のアプローチが、入力が直接文字列連結に利用され、実行可能な SQL ステートメントを構築している箇所で使用されていないことを確認します。

string sql = "select status from Users where UserName='" 
+ txtUserName.Text + "'";

4.

コードが入力のフィルタ処理を試行するどうかを確認します。
一般的なアプローチでは、SQL に特別な意味を持つ文字にエスケープ文字を追加するルーチンをフィルタします。これはあまり安全なアプローチとは言えず、また表記の問題があるため、この方法に依存することはできません。

バッファ オーバーフロー

バッファ オーバーフローのコード レビューでは、P/Invoke または COM Interop 層経由でアンマネージ コードを呼び出すコードを特にレビューしてください。配列がアクセスするすべての箇所で配列範囲が自動的に確認されるため、マネージ コード自体のバッファ オーバーフローに対する脆弱性はそれほど大きくありません。Win32 DLL または COM オブジェクトを呼び出したら直ちに、その API 呼び出しを慎重に検査する必要があります。

次の手順は、バッファ オーバーフローに対する脆弱性を確認するうえで役立ちます。

1.

アンマネージ コード呼び出し箇所を検索します。
ソース ファイルを、アンマネージ コード呼び出しに使用する名前空間名「System.Runtime.InteropServices」で検索します。

2.

アンマネージ API に渡される文字列パラメータを確認します。
これらのパラメータはバッファ オーバーフローのプライマリ ソースです。入力文字列の長さが API の定めた制限を超えないことをコードが検証することを確認します。アンマネージ API が文字ポインタを受け取る場合、アンマネージ ソースにアクセスしない限り、最大有効文字列長さを知ることができません。一般的な脆弱性を以下のコード フラグメントに示します。

void SomeFunction( char *pszInput )
{
char szBuffer[10];
// 要注意、長さ確認が行われていません。入力はバッファへ直接コピーされます。
// 長さを確認するか、strncpy を使用する必要があります。
strcpy(szBuffer, pszInput);
  . . .
}

注: strncpy はコピーされる文字数を制限するだけでコピー先に十分な領域があるかどうかの確認は行わないため、strncpy を使用してもバッファ オーバーフローが発生する場合があります。

アンマネージ コードを所有していないため検査できない場合は、意図的に長くした入力文字列や無効な引数を使用して、API を厳密にテストしてください。

3.

ファイル パスの長さを確認します。
アンマネージ API がファイル名やファイル パスを受け取る場合、ファイル名やファイル パスが 260 文字を超えないことをラッパー メソッドが確認することを確認してください。これは Win32 の MAX_PATH 定数で規定された値です。ディレクトリ名およびレジストリ キーは最大 248 文字であることにも注意してください。

4.

出力文字列を確認します。
コードが StringBuilder を使用してアンマネージ API から送り返された文字列を受け取ることを確認します。アンマネージ コードからは任意の長さの文字列が送り返されるため、StringBuilder の容量がアンマネージ API が送り返す最大文字列に足りることを確認します。

5.

配列範囲を確認します。
配列を使用してアンマネージ API へ入力を渡す場合、配列の容量を超えないことをマネージ ラッパーが確認することを確認します。

6.

アンマネージ コードが /GS スイッチでコンパイルされていることを確認します。
アンマネージ コードを所有している場合、GS スイッチを使用してスタック プローブでバッファ オーバーフローを検出してください。

マネージ コード

ここのレビュー項目を使用して、マネージ ソース コード全体を分析してください。レビュー項目はアセンブリの種類に関係なく使用することができます。ここでは、一般的なマネージ コードの脆弱性を識別するうえで役立ちます。ここで説明した問題の詳細、および脆弱性を説明したコード サンプルについては、モジュール 7「セキュリティ保護されたアセンブリを構築する」を参照してください。

マネージ コードに明示的なコード アクセス セキュリティ機能を使用している場合は、関連するレビュー ポイントについて、このモジュールの「コード アクセス セキュリティ」を参照してください。次のレビュー項目を使用すると、マネージ コードの脆弱性を識別するうえで役立ちます。

クラス デザインのセキュリティ保護

スレッドの作成

シリアル化の使用

リフレクションの使用

例外の処理

暗号化の使用

機密情報の格納

委任の使用

クラス デザインのセキュリティ保護

アセンブリは、含まれるクラスや他の型と同程度のセキュリティでしか保護されません。次のレビュー項目は、クラス デザインのセキュリティをレビューするうえで役立ちます。

型およびメンバの参照範囲の制限
public に指定されている型またはメンバのすべてについてレビューを行い、アセンブリのパブリック インターフェースの必要な一部であることを確認します。

非基底クラスのシールド設定
クラスを派生させたくない場合は、キーワード "sealed" を使用して、コードが潜在的に悪意のあるサブクラスに誤用されることを防ぎます。

パブリックな基底クラスについては、コード アクセス セキュリティの継承要求を使用して、クラスから継承できるコードに制限することができます。これは、重層的な防御に有効です。

フィールドの公開に対するプロパティの使用
クラスが直接フィールドを公開していないことを確認してください。プロパティは、プライベート以外のフィールドの公開に使用してください。このことにより、入力値を検証し、セキュリティ チェックを追加することになります。

読み取り専用プロパティの使用
読み取り専用プロパティを効果的に使用していることを確認します。フィールドが読み取り専用を設定するデザインになっていない場合は、get アクセサだけを追加して、読み取り専用プロパティを実装します。

仮想内部メソッドの使用
これらのメソッドはクラスにアクセスした他のアセンブリにオーバーライドされることがあります。宣言型チェックを使用するか、または必要条件でない場合はキーワードの virtual を削除してください。

IDisposable の実装
実装している場合は、オブジェクト インスタンスが終了したときに Dispose メソッドを呼び出して、すべてのリソースが開放されていることを確認します。

スレッド の作成

マルチスレッド コードは、見つけにくいタイミング関連のバグまたはセキュリティの脆弱性の原因となりうる競合を引き起こしやすいコードです。マルチスレッド コードの場所を確認するには、以下のコード フラグメントに示すようにソース コードを「Tread」で検索して、新しい Tread オブジェクトが作成された場所を識別してください。

Thread t = new Thread(new ThreadStart(someObject.SomeThreadStartMethod));

次のレビュー項目を使用すると、スレッドの脆弱性を識別するうえで役立ちます。

コードによるセキュリティ チェックの結果のキャッシュ
静的変数やグローバル変数などの形でコードのセキュリティ チェック結果がキャッシュされ、そのフラグを使用して次のセキュリティに関する決定が行われる場合、そのコードは競合に対して特に脆弱になります。

コードの偽装
新しいスレッドを作成するスレッドは現在偽装していますか。新しいスレッドは、既存のスレッドのセキュリティ コンテキストではなく、プロセス レベルのセキュリティ コンテキストを取得します。

コードにおける静的クラス コンストラクタ
複数のスレッドが同時にアクセスする場合にも、静的クラスのコンストラクタが脆弱でないことを確認します。必要に応じて、スレッドを同期させ、同時アクセスを防ぎます。

Dispose メソッドの同期
オブジェクトの Dispose メソッドが同期されていない場合、2 つのスレッドが同じオブジェクトに対して Dispose を実行する可能性があります。この同時実行は、特に cleanup コードがファイル、プロセス、スレッド処理などのアンマネージ リソース ハンドラを開放した場合、セキュリティ問題を発生させる可能性があります。

シリアル化の使用

シリアル化をサポートするクラスは SerializableAttribute に指定されるか、あるいは Iserializable から派生します。シリアル化をサポートするクラスは、文字列 Serializable のテキスト検索によって見つけることができます。次に、以下の問題についてコードをレビューします。

クラスでの機密性の高いデータの含有
機密性の高いデータが含まれる場合、[NonSerialized] 属性に指定、あるいは ISerializable を実装してどのフィールドがシリアル化されるかを制御することによって、コードが機密性の高いデータのシリアル化を防いでいることを確認します。

クラスが機密性の高いデータをシリアル化する必要がある場合、データの保護方法についてレビューします。まずデータの暗号化を検討します。

クラスへの Iserializable の実装
実装している場合、クラスは AllowPartiallyTrustedCallersAttribute を含まない強固な名前のアセンブリにインストールされた呼び出し元など、完全に信頼された呼び出し元だけをサポートしていますか? クラスが部分的に信頼された呼び出し元をサポートしている場合、GetObjectData メソッド実装節が適切なアクセス許可を要求を使用して呼び出しコードを承認することを確認してください。"StrongNameIdentityPermission" 要求を使用してオブジェクトをシリアル化できるアセンブリを制限する手法が有効です。

クラスによるデータ ストリームの検証
コードにシリアル化されたデータ ストリームを受け取るメソッドが含まれる場合、すべてのフィールドがデータ ストリームから読み出されたときに検証されることを確認します。

リフレクションの使用

リフレクションを使用するコードを確認するには、リフレクション型を含む名前空間の "System.Reflection" で検索を行います。リフレクションを使用する場合、次のレビュー項目を確認すると、潜在的な脆弱性を識別するうえで役立ちます。

アセンブリの動的な読み込み
コードがアセンブリを読み込んでオブジェクト インスタンスの作成または型の呼び出しを行う場合、そこに入力データから得られたアセンブリまたは型の名前が含まれますか。含まれる場合、コードがアクセス許可の要求で保護され、すべての呼び出しコードが承認されていることを確認します。たとえば、StrongNameIdentity によるアクセス許可の要求または完全信頼の要求を使用してください。

ランタイムでの動的なコードの作成
アセンブリがコードを動的に生成して呼び出し元に対する処理を実行する場合、生成されるコードは呼び出し元から何の影響も受けないことを確認します。たとえば、コードの生成は呼び出し元からの入力パラメータに依存していますか。入力パラメータに依存することは避けてください。どうしても必要な場合は、入力が検証されており、悪用してコードの生成に影響を与えることができないことを確認してください。

他の型に対するリフレクションの使用
使用する場合は、信頼されたコードからしか呼び出されないことを確認してください。コード アクセス セキュリティ許可を要求して、呼び出しコードを承認してください。

例外の処理

セキュリティで保護された例外処理は、堅牢なコードに必要です。例外の詳細なログを確実に記録して問題の診断に役立て、内部システムの詳細がクライアントに公開されるのを確実に防ぎます。次のレビュー項目を確認すると、例外処理の脆弱性を識別するうえで役立ちます。

初期段階での障害の発生
リソースを消費する不要な処理を回避するため、コードが早い段階で障害を発生させることを確認します。コードに障害が発生した場合、そのエラーによってユーザーがセキュリティ チェックを回避して権限によるコードを実行できるようにならないことを確認します。

例外の処理方法
呼び出し元にシステムまたはアプリケーションの詳細を公開することは避けてください。たとえば、呼び出しスタックをエンド ユーザーに返さないでください。try/catch ブロックに関する例外を生成する可能性のあるリソース アクセスまたは操作はラップします。処理方法を知っている例外のみ処理し、特定の例外を一般的なラッパーで処理することは避けてください。

例外の詳細のログ記録
問題の診断に役立てるため、例外の詳細ログが例外のソースに記録されていることを確認します。

例外フィルタの使用
使用する場合は、呼び出しスタックの上の方にあるフィルタのコードは、finally ブロックのコードより前に実行されることに注意してください。finally ブロックの状態の変更は例外フィルタの実行の後に行われるため、finally ブロックでの状態の変更に依存していないことを確認します。

例外フィルタの脆弱性の例については、モジュール 7「セキュリティ保護されたアセンブリを構築する」の「例外管理」を参照してください。

暗号化の使用

使用する場合は、コードが自身の暗号化ルーチンを実装していないことを確認します。暗号化ルーチンを実装する代わりに、名前空間 System.Security.Cryptography、あるいはデータ保護 API (DPAPI) などの Win32 暗号化を使用する必要があります。次のレビュー項目を確認すると、潜在的な暗号化関連の脆弱性を識別するうえで役立ちます。

対称暗号化の使用
対称暗号化を使用し、暗号化されたデータを長期間変動させずにおく必要がある場合には、Rijndael (AES (Advanced Encryption Standard) または 3DES (Triple Data Encryption Standard) と呼びます) を使用することを確認します。脆弱な (ただし速い) RC2 や DES アルゴリズムは、セッション データなどデータを短期間だけ暗号化する場合に使用してください。

最大サイズのキーの使用
使用しているアルゴリズムで最も大きなサイズのキーを使用してください。キーのサイズが大きいとキーに対する攻撃はより困難になりますが、パフォーマンスが低下します。

ハッシュの使用
使用する場合で、共有の機密情報を知っていることを証明するプリンシパルが必要な場合は、MD5 や SHA1 を使用することを確認してください。たとえば、チャレンジ/レスポンス認証では、パスワードをサーバーに渡すことなくクライアントがパスワードを知っていることを証明するために、ハッシュが使用されます。クライアントとのキーの共有が必要となるメッセージ認証コード (MAC) と共に HMACSHA1 を使用してください。このことにより、セキュリティ チェックを統合し、ある程度十分な認証を行うことができます。

暗号化のための乱数の生成
暗号化のための乱数を生成する場合は、コードが Random クラスではなく System.Security.Cryptography.RNGCryptoServiceProvider クラスを使用して乱数を生成することを確認します。Random クラスでは、繰り返し不可能または予測不可能な真の乱数は生成されません。

機密情報の格納

アセンブリが機密情報を格納する場合、デザインをレビューして機密情報の格納が絶対必要であることを確認します。機密情報を格納する必要がある場合、次のレビュー項目を確認してできるだけセキュリティで保護してください。

機密情報のメモリへの保存
機密情報をプレーンテキストの状態でメモリに長期間格納しないでください。ストアから取得した機密情報を復号化して使用したら、機密情報が格納されていた領域をゼロに置き換えてください。

プレーンテキストのパスワードまたは SQL 接続文字列の、Web.config または Machine.config への保存
これは行わないでください。aspnet_setreg.exe を使用して、暗号化された資格情報を <identity>、<identity>、および <identity> 要素のレジストリに格納してください。Aspnet_setreg.exe の取得および使用方法の詳細については、マイクロソフト サポート技術情報の 329290「[HOWTO] ASP.NET ユーティリティを使用して資格情報およびセッション状態の接続文字列を暗号化する方法」を参照してください。

機密情報を暗号化する方法
接続文字列や資格情報が DPAPI を使用して暗号化されていることを確認します。LSA へのアクセスに使用されるアカウントは管理権限を必要とするため、ローカル セキュリティ機関 (LSA) に機密情報を格納しないでください。DPAPIの使用方法の詳細については、「セキュリティ保護された ASP.NET アプリケーションの構築」の「パート IV : 参照」の「作業の手引き」セクションの「DPAPIライブラリを作成する方法」を参照してください。

機密情報のレジストリへの保存
格納する場合は、その情報が最初に暗号化されること、および格納先が HKEY_LOCAL_MACHINE の場合は制限付き ACL で保護されることを確認してください。コードが HKEY_CURRENT_USER を使用している場合、関連ユーザー アカウントでの実行が自動的に制限されるため、ACL での保護は必要ありません。

リバース エンジニアリングの問題
心配な場合は、難読化ツールの使用を検討してください。詳細については、難読化ツールのリスト「OBFUSCATORS」(英語) を参照してください。

注: 機密データの隠蔽を暗号化ツールに依存しないでください。暗号化ツールを使用すると機密データの識別がより困難になりますが、問題は解決されません。

委任の使用

どのコードも、メソッドと委任を関連付けることができます。委任には、低い信頼レベルで実行される潜在的に悪意のあるコードも含まれます。

信頼関係にないソースからの委任の受け取り
受け取る場合は、SecurityAction.PermitOnly によるセキュリティ許可を使用して、委任 メソッドへのアクセス許可が制限されていることを確認してください。

委任の呼び出し前におけるアサートの使用
それが何を行う委任 コードか呼び出し前には分からないため、これは行わないようにしてください。

コード アクセス セキュリティ

すべてのマネージ コードに対し、コード アクセス セキュリティ許可が要求されます。問題の多くは、コードが部分的に信頼された環境で使用され、コードまたは呼び出しコードがコード アクセス セキュリティ ポリシーから十分に信頼されない場合にのみ、発生します。

ここで説明した問題の詳細については、モジュール 8「コード アクセス セキュリティの実践」を参照してください。

以下のレビュー ポイントを使用して、適切で安全なコード アクセス セキュリティが使用されていることを確認してください。

部分的に信頼された呼び出し元のサポート

パブリックな型およびメンバへのアクセスの制限

宣言型セキュリティの使用

Assert の呼び出し

必要に応じた、アクセス許可の要求の使用

リンク確認要求の使用

Deny または PermitOnly の使用

特に危険なアクセス許可の使用

/unsafe オプションを指定したコンパイル

部分的に信頼された呼び出し元のサポート

コードが部分的に信頼された呼び出し元をサポートする場合、攻撃される危険性が大きくなります。その結果、広範囲に渡る徹底したコード レビューを行うことが特に重要になります。Web アプリケーションの <trust> レベルが、部分的に信頼されたレベルで実行される設定になっているかどうかを確認してください。この設定になっている場合、そのアプリケーション用に開発されるアセンブリは、部分的に信頼された呼び出し元をサポートする必要があります。

次のレビュー項目を確認すると、潜在的に脆弱な領域を識別するうえで役立ちます。

アセンブリに対する強固な名前付け
強固な名前付けが行われている場合、既定のセキュリティ ポリシーでは、部分的に信頼された呼び出し元からは呼び出せない設定になっています。完全な信頼へのリンク確認要求が、共通言語ランタイム (CLR) により暗黙的に出されます。アセンブリに強固な名前が付けられていない場合、明示的に完全な信頼を要求するなど呼び出し元を制限する明示的な方法を取らない限り、そのアセンブリはどのコードからも呼び出すことができます。

注: ASP.NET アプリケーションに呼び出される強固な名前のアセンブリは、グローバル アセンブリ キャッシュにインストールする必要があります。

APTCA の使用
強固な名前のアセンブリに AllowPartiallyTrustedCallersAttribute が含まれる場合、部分的に信頼された呼び出し元はコードを呼び出すことができます。この場合、アセンブリによって実行されるリソースへのアクセスなどの権限による操作は、他のコード アクセス セキュリティ要求で承認および保護されていることを確認してください。.NET Framework クラス ライブラリを使用してリソースにアクセスする場合、自動的に完全なスタック ウォーク要求が出されます。コードが Assert 呼び出しを使用してスタック ウォークを妨げない限り、呼び出しコードは承認されます。

オブジェクト参照の引き渡し
メソッドの戻り値および ref パラメータを確認して、コードがオブジェクト参照を返す場所を確認してください。部分的に信頼されたコードが、完全に信頼された呼び出し元へのアクセスを要求するアセンブリから取得されたオブジェクトに参照を渡さないことを確認します。

パブリックな型およびメンバへのアクセスの制限

コード アクセス セキュリティ ID 要求を使用して、パブリックな型およびメンバへのアクセスを制限することができます。これは、アセンブリが攻撃を受ける危険性を減らすのに役立ちます。

呼び出し元の制限における ID 要求の使用
特定のアプリケーション内で特定のアセンブリによってのみ使用されるクラスまたは構造については、ID 要求を使用して呼び出し元の範囲を制限することができます。たとえば、StrongNameIdentityPermission を使用して要求すると、要求された公開キーに対応する署名付き秘密キーを持つ特定のアセンブリに呼び出し元を制限することができます。

サブクラスの制限に対する継承要求の使用
特定のコードのみが基底クラスからの継承を必要とすることが分かっている場合、クラスが StrongNameIdentityPermission を使用して継承要求することを確認します。

宣言型セキュリティ属性の使用

宣言型セキュリティ属性は Permview.exe. などのツールを使用して表示させることができます。これは、アセンブリの利用者および管理者がコードのセキュリティ要件を理解するうえで非常に役立ちます。

最小限のアクセス許可の要求
.RequestMinimum 文字列を検索して、コードがアクセス許可の要求を使用して最小アクセス許可要件を特定しているかどうかを確認してください。これは、アセンブリのアクセス許可の要求を明確に記録するために必ず行ってください。

必要に応じたアクセス許可の要求、またはアクセス許可の拒否
文字列 .RequestOptional と .RequestOptional を検索してください。この2 つのアクションのいずれかを使用して最小権限のコードを開発した場合、そのコードは AllowPartiallyTrustedCallersAttribute で指定されない限り強固な名前のアセンブリを呼び出せなくなることに注意してください。

宣言型セキュリティではなく強制型セキュリティの使用
ロジックを適用してどの許可を要求すべきかの決定しなくてはならない、または要求にランタイム変数が必要なために、コードに強制型チェックが必要となる場合があります。特定のロジックが必要でないなら、アセンブリのアクセス許可の要求を記録するために、宣言型セキュリティの使用を検討してください。

クラスとメンバのレベル属性の組み合わせ
これは行わないでください。メソッドやプロパティなどのメンバ属性はクラス レベル属性を同じセキュリティ アクションと置き換えるため、これらと結合しないでください。

Assert の呼び出し

Assert 呼び出しについてコードを検索してください。この検索により Debug.Assert のインスタンスが見つかることがあります。コードがどこで CodeAccessPermission オブジェクトに Assert を呼び出すかを探します。コード アクセス許可をアサートする場合は、危険性のあるプラクティスであるスタック ウォークを要求するコード アクセス セキュリティ許可を回避してください。悪意のある呼び出し元が、セキュリティで保護されたリソースまたは権限による操作にアクセスするアサートを行えないようにするための、コードにおける処理方法を確認してください。次のレビュー項目を確認してください。

Demand と Assert のパターンの使用
コードが Demand を Assert より前に発行することを確認してください。コードは、アンマネージ コードの許可などの広範な許可がアサートされる前に、呼び出し元を承認する細かい許可を要求する必要があります。

Assert 呼び出しと RevertAssert 呼び出しとのマッチング
各 Assert 呼び出しと RevertAssert 呼び出しが対応していること確認してください。Assert を呼び出すメソッドが戻されると Assert は暗黙的に削除されますが、優れたプラクティスでは Assert 呼び出し後できるだけ迅速に RevertAssert を明示的に呼び出します。

アサート時間の短縮
必要最小限の時間だけアサート許可が与えられていることを確認してください。たとえば、別のメソッドを呼び出す間だけ Assert 呼び出しを使用する必要がある場合、そのメソッド呼び出し後直ちに RevertAssert が呼び出されていることを確認してください。

必要に応じた、アクセス許可の要求の使用

コードは常に .NET Framework クラス ライブラリからのアクセス許可の要求チェックを受けますが、コードが明示的なアクセス許可の要求を使用する場合、適切に要求されていることを確認してください。コードを文字列. Demand で検索して、宣言型または強制型のアクセス許可の要求のどちらであるかを識別し、次に次のレビュー項目を確認します。

データのキャッシュ
キャッシュする場合、キャッシュされたデータにアクセスする前にコードが適切なアクセス許可の要求を発行しているかどうかを確認してください。たとえば、データがあるファイルから取得され、その呼び出しコードがキャッシュを割り当てたファイルへアクセスできる承認を受けたことを確認したい場合、キャッシュされたデータにアクセスする前に FileIOPermission を要求します。

カスタム リソースまたは権限による操作の公開
コードがアンマネージ コードを通じてカスタム リソースまたは権限による操作を公開する場合、適切なアクセス許可の要求が発行されることを確認します。この要求はリソースの性質によって、ビルトイン許可型のこともあればカスタム許可型のこともあります。

初期段階でのアクセス許可の要求
アクセス許可の要求が、リソースへのアクセスまたは権限による操作を行う前に発行されていることを確認してください。リソースにアクセスし、その次に呼び出し元の承認を行わないでください。

冗長アクセス要求の発行
.NET Framework のクラス ライブラリを使用するコードは、アクセス許可を要求されます。コードは同じアクセス要求を発行する必要がありません。同じアクセス要求を発行すると、スタック ウォークの重複または無駄になります。

リンク確認要求の使用

一般的な確認要求とは異なり、リンク確認要求はコードの直接の呼び出し元だけをチェックします。完全なスタック ウォークは実行されないため、リンク確認要求を使用するコードはおとり攻撃にさらされます。おとり攻撃の詳細については、モジュール 8「コード アクセス セキュリティの実践」を参照してください。

コードを文字列 .LinkDemand で検索し、リンク確認要求が使用されている箇所を識別してください。これらは宣言的にのみ使用されます。一例を以下のコード フラグメントに示します。

[StrongNameIdentityPermission(SecurityAction.LinkDemand,  
PublicKey="00240000048...97e85d098615")]
public static void SomeOperation() {}

ここで説明した問題の詳細については、モジュール 8「コード アクセス セキュリティの実践」の「リンク要求」を参照してください。次のレビュー項目は、コードのリンク確認要求の使用法についてレビューするうえで役立ちます。

リンク確認要求使用の理由
防御を考慮したアプローチでは、リンク確認要求をできるだけ避けます。単にパフォーマンスを向上させるためや完全なスタック ウォークを取り除くためだけに使用しないでください。ネットワークの遅延やデータベース アクセスなど他の Web アプリケーションのパフォーマンス問題のコストに比べ、スタック ウォークのコストは小さいです。リンク確認要求は、どのコードによりコードが呼び出されるかを把握していて、それを制限できる場合のみ安全です。

呼び出し元の信頼性
リンク確認要求を使用する場合、おとり攻撃の防止をを呼び出し元に依存しています。リンク確認要求は、コードの直接の呼び出し元を正確に知っていてそれを制限でき、またその先の呼び出し元を呼び出し元が承認すると信頼できる場合にのみ、安全です。

リンク確認要求での保護されたコードの呼び出し
呼び出す場合、コードは、コードの呼び出し元からのセキュリティ アクセス許可の要求による承認を提供する必要があります。メソッドへ渡された引数が呼び出すコードへ渡されるかどうかを確認してください。渡される場合、その引数が、呼び出したコードに悪意のある影響を与える可能性があるかどうかも確認します。

メソッドおよびクラス レベルでのリンク確認要求の使用
リンク確認要求をメソッドに追加すると、クラスのリンク確認要求がオーバーライドされます。メソッドにクラス レベルのリンク確認要求も含まれることを確認してください。

シールされていないクラスでリンク確認要求の使用
リンク確認要求は派生型に継承されず、またオーバーライドされたメソッドが派生型に呼び出された場合、使用されません。リンク確認要求で保護される必要のあるメソッドをオーバーライドする場合は、そのリンク確認要求をオーバーライドされたメソッドに適用してください。

構造の保護に対するリンク確認要求の使用
リンク確認要求は、信頼関係にない呼び出し元が構造を構成することを防げません。これは、既定のコンストラクタが構造に対して自動的に生成され、構造レベルのリンク確認要求は明示的なコンストラクタを使用した場合にのみ適用されるからです。

明示的なインターフェイスの使用
Interface をキーワードにして検索してください。見つかった場合、メソッド実装節にリンク確認要求が設定されているかどうか確認します。設定されている場合、インターフェイスの定義に同じリンク確認要求が含まれていることを確認してください。同じリンク確認要求が含まれていない場合、呼び出し元がリンク確認要求をバイパスする可能性があります。

潜在的に危険なアクセス許可の使用

以下のアクセス許可型が信頼できるコードにのみ付与されていることを確認してください。これらのほとんどは独自のアクセス許可型を持たず、一般的な SecurityPermission 型を使用します。これらの型を使用するコードを綿密に検査して、その危険性が最小限に抑えられていることを確認する必要があります。また、これらのアクセス許可をどうしても使用しなくてはならない理由も必要です。

表 21.3: 危険なアクセス許可

アクセス許可 説明

SecurityPermission.UnmanagedCode

アンマネージ コードを呼び出すことができます。

SecurityPermission.SkipVerification

安全な型であることを検証される必要がなくなります。

SecurityPermission.ControlEvidence

セキュリティ ポリシーの評価に使用する自身のエビデンスを自身で提供できます。

SecurityPermission.ControlPolicy

ポリシーを表示および変更できます。

SecurityPermission.ControlEvidence

シリアル化を使用できます。

SecurityPermission.ControlEvidence

承認に使用されるプリンシパル オブジェクトを操作できます。

SecurityPermission.SkipVerification

リフレクションを介して型のプライベート メンバを呼び出すことができます。

SecurityPermission.ControlAppDomain

新しいアプリケーション ドメインを作成することができます。

SecurityPermission.ControlDomainPolicy

Domain Policy を変更できます。

/unsafe オプションを指定したコンパイル

Visual Studio .NET を使用して、プロジェクトのプロパティの Allow Unsafe Code Blocks が true に設定されていることを確認してください。これにより /unsafe コンパイラ フラッグが立てられ、コードが安全でないブロックを含むことをコンパイラに通知し、最小アクセス許可 SkipVerification をアセンブリに付与するよう要求します。

/unsafe でコンパイルする場合、そうしなくてはならない理由についてレビューしてください。合理的な理由がある場合は、潜在的な脆弱性がないかソース コードを特に注意してレビューしてください。

アンマネージ コード

Win32 DLL や COM オブジェクトなどのアンマネージ コードを呼び出すコードはセキュリティ リスクが高いため、特に注意してください。アンマネージ コードは安全であることが検証できる型ではなく、潜在的にバッファ オーバーフローを招くものです。アンマネージ コードからのリソースへのアクセスにはコード アクセス セキュリティ チェックが行われません。これはマネージ ラッパー クラスの責任範囲になります。

アンマネージ コードは、通常は部分的に信頼された呼び出し元に直接公開しないでください。ここで説明した問題の詳細については、モジュール 7「セキュリティ保護されたアセンブリを構築する」およびモジュール 8「コード アクセス セキュリティの実践」を参照してください。

次のレビュー項目を使用して、アンマネージ コードの使用について検証してください。

アンマネージ コードのアクセス許可のアサート

アサートする場合は、コードが Assert メソッドの呼び出し前に適切なアクセス許可を要求して、すべての呼び出し元がリソースへのアクセスまたはアンマネージ コードに公開される操作の承認を確実に受けることを確認してください。たとえば、以下のコード フラグメントでは、カスタム暗号化許可を要求してからアンマネージ コードのアクセス許可をアサートする方法が示されています。

// カスタム暗号化許可を要求します。
(new EncryptionPermission(
EncryptionPermissionFlag.Encrypt, storeFlag)).Demand();
// アンマネージ コードのアクセス許可をアサートします。
(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
// ここで P/Invoke を使用してアンマネージ DPAPI 機能を呼び出します。

詳細については、モジュール 8「コード アクセス セキュリティの実践」の「Assert および RevertAssert」を参照してください。

SuppressUnmanagedCodeAttribute の使用
この属性はマネージ コードがアンマネージ コードを呼び出す際に自動的に発行されるアンマネージ コードのアクセス許可要求を抑制します。P/Invoke メソッドまたは COM Interop インターフェイスにこの属性が設定されている場合、アンマネージ コードの呼び出しにつながるすべてのコードのパスが、呼び出し元を承認するセキュリティ アクセス許可で保護されていることを確認してください。この属性がメソッド レベルで使用され、クラス レベルでは使用されていないことも確認してください。

注: SupressUnmanagedCodeSecurityAttribute を適用すると、Interop 層からの暗黙的な UnmanagedCode アクセス許可の要求が、LinkDemand に変更されます。つまり、コードがおとり攻撃に対して脆弱になります。

アンマネージ エントリ ポイントの公開
アンマネージ エントリ ポイントが private または internal に指定されていることを確認してください。アンマネージ コードをカプセル化するマネージ ラッパー メソッドを呼び出し元に強制的に呼び出させることが必要です。

バッファ オーバーフローに対する防御
アンマネージ コードはバッファ オーバーフローなどの入力攻撃を受けやすいコードです。アンマネージ コード API がパラメータの型と長さが確認する必要があります。ただし、アンマネージ コードを所有しない可能性があるため、この確認に依存することはできません。したがって、マネージ ラッパー コードの入力および出力パラメータは厳密に検査される必要があります。詳細については、このモジュールの「バッファ オーバーフロー」を参照してください。

注: C および C++ に適用されるコード レビュー ルールと統制すべてがアンマネージ コードに適用されます。

列挙型の範囲の確認
ネイティブ メソッドに渡す前に、すべての列挙値が範囲内であることを確認してください。

アンマネージ コード メソッド用の名前付け規則の使用
すべてのアンマネージ コードは、次の名前を持つラッパー クラスに入っている必要があります。NativeMethods、UnsafeNativeMethods、および SafeNativeMethods の 3 つです。ネイティブ API に渡される UnsafeNativeMethods 内のコードおよびパラメータはセキュリティに対して脆弱なため、すべて徹底的にレビューする必要があります。

潜在的に危険な API の呼び出しの確認
すべての Win32 API 呼び出しの使用を正当化できることが必要です。危険な API は次のとおりです。

セキュリティ コンテキストを切り替えるスレッド機能

セキュリティ トークンに関する情報を変更または公開できる、アクセス トークン機能

トークン作成機能などの、資格情報管理機能

秘密キーの復号や秘密キーへのアクセスを行うことのできる暗号化 API 機能

メモリの読み込みや書き込みができるメモリ管理機能

システムの機密情報にアクセスできる LSA 機能

ASP.NET のページおよびコントロール

このセクションのレビュー項目を使用して、ASP.NET のページおよびコントロールをレビューしてください。ここで説明した問題の詳細については、モジュール 10「セキュリティ保護された ASP.NET ページとコントロールを構築する」を参照してください。

エラー メッセージの詳細表示の無効化

トレースの無効化

フォーム フィールド入力の検証

XSS 攻撃に対する脆弱性

クエリ文字列と Cookie 入力の検証

セキュリティの HTTP ヘッダへの依存

ビュー ステートのセキュリティ保護

XSS の防御

Global.asax のイベント ハンドラのセキュリティ保護

適切な承認の実行

エラー メッセージの詳細表示の無効化

アプリケーションの範囲を超えた例外が適用されると、ASP.NET が詳細な情報を呼び出し元に返す場合があります。この情報には、攻撃者にとって有用な完全なスタック トレースなどの情報も含まれます。<customErrors> 要素の、モード属性が On または RemoteOnly に設定されていることを確認してください。

<customErrors mode="On" defaultRedirect="YourErrorPage.htm" />

トレースの無効化

トレース情報も攻撃者にとって非常に有用です。<customErrors> 要素で、トレースが無効になっていることを確認してください。

<trace enabled="false" localOnly="true" pageOutput="false"  
       requestLimit="10" traceMode="SortByTime"/>

フォーム フィールド入力の検証

ポストされたフォーム フィールド経由で、攻撃者が悪意のある入力を Web ページおよびコントロールに渡すことがあります。隠しフォーム フィールドを含むすべてのフォーム フィールドが検証されていることを確認します。フォーム フィールドの型、範囲、フォーマット、および長さを検証してください。次のレビュー項目を使用して、ASP.NET の入力処理をレビューしてください。

入力にファイル名やパスが含まれている
これは危険性の高い操作のため、通常は避けてください。なぜユーザー名に基づいてアプリケーションが場所を選択するのでなく、ユーザーがファイル名やパスを指定しなくてはいけないのでしょうか。

ファイル名やパスを入力値として受け取る場合、コードは正規化バグに対して脆弱になります。ユーザーからパス入力を受け取らなくてはならない場合、安全で正規化されたパスであると検証されていることを確認してください。コードが System.IO.Path.GetFullPath を使用していることを確認してください。

MapPath の呼び出し
ユーザー指定のファイル名を含む MapPath を呼び出す場合、コードが bool パラメータを受け取る HttpRequest.MapPath をオーバーライドして、クロス アプリケーション マッピングを防ぐことを確認してください。

try
{
  string mappedPath = Request.MapPath( inputPath.Text,  
                                       Request.ApplicationPath, false);
}
catch (HttpException)
{
// クロス アプリケーション マッピングを実行しようとしました。
}

詳細については、モジュール 10「セキュリティ保護された ASP.NET ページとコントロールを構築する」の「MapPath を使用する」を参照してください。

データ型の検証方法
ポストされたフォーム フィールド、クエリ文字列などの他の Web フォームから受け取られたデータのデータ型を、コードが検証することを確認してください。文字列以外のデータについては、コードが .NET Framework の型システムを使用して型チェックすることを確認してください。文字列を強固な型のオブジェクトに変換して、すべての型変換の例外を把握することができます。たとえばフィールドに日付が含まれる場合、この日付を使用して System.DateTime オブジェクトを構築することができます。年表示の年齢が含まれる場合、Int32.Parse を使用して Int32.Parse オブジェクトに変更し、フォーマットの例外を把握することができます。

文字列型の検証方法
入力文字列について、長さ、指定された範囲の文字グループ、および文字列パターンであることが、正規表現を条件として検証されていることを確認します。RegularExpressionValidator 検証コントロールを使用、または RegEx クラスを直接使用することができます。無効なデータの検索は行わず、正しいと分かっているフォーマット情報についてのみ検索してください。

検証コントロールの使用
RegularExpressionValidator、RequiredFieldValidator、CompareValidator、RangeValidator、CustomValidator などの検証コントロールを使用する場合、サーバー側の検証を無効化しておらず、またクライアント側の検証だけに依存していないことを確認してください。

クライアント側の検証への依存
これは行わないでください。クライアント側の検証は、ユーザー エクスペリエンスを向上させるためだけに使用してください。すべての入力がサーバー側で検証されていることを確認してください。

XSS 攻撃に対する脆弱性

XSS に対する脆弱性について、必ず Web ページをレビューしてください。詳細については、このモジュールの「クロスサイト スクリプティング」を参照してください。

クエリ文字列と Cookie の入力の検証

コードが、URL クエリ文字列から渡された入力フィールドおよび Cookie から抽出された入力フィールドを検証することを確認してください。以下のテキスト文字列を検索して、脆弱なコードを見つけます。

Request.QueryString

Request.Cookies

入力値の型、範囲、フォーマット、および長さが、型付けされたオブジェクトおよび正規表現を使用して、フォーム フィールドに対してと同様に検証されることを確認してください (前述した「フォーム フィールド入力の検証」を参照してください)。無効なコンストラクトを打ち消してしまうと XSS バグにつながるおそれがあるため、ユーザー入力から派生するすべての HTML や URL エンコード出力についても考慮してください。

ビュー ステートのセキュリティ保護

アプリケーションがビュー ステートを使用する場合、不正操作は防止されているかどうかを確認します。次のレビュー項目を確認してください。

アプリケーション レベルでのビュー ステート保護の有効化
アプリケーションの Machine.config または Web.config ファイルの <pages> 要素の "enableViewState" 属性でビュー ステートがアプリケーション レベルで保護されているかどうかを確認してください。次に、"enableViewStateMac" が "true" に設定され、不正操作を確実に防止することを確認します。

<pages enableViewState="true" enableViewStateMac="true" />

ページ単位でのビュー ステート保護のオーバーライド
Web ページの一番上にあるページ レベル コマンドで、そのページのビュー ステートが有効になっていることを確認します。enableViewStateMac を探し、見つかった場合は true に設定されていることを確認します。enableViewStateMac が含まれておらず true に設定されている場合、そのページは Web.config ファイルで指定されたアプリケーション レベルの既定の設定になっていると考えられます。enableViewState が false に設定されてそのページのビュー ステートが無効になっている場合、この保護設定は関係ありません。

コードのビュー ステート保護のオーバーライド
Page.EnableViewStateMac プロパティを false に設定することによるビュー ステート保護を無効化を、コードが行っていないことを確認してください。これはそのページがビュー ステートを使用しない場合のみ、安全な設定です。

Global.asax のイベント ハンドラのセキュリティ保護

Global.asax ファイルには、ASP.NET および HTTP モジュールで生成されるアプリケーション レベルのイベント用のイベント ハンドラ コードが含まれています。以下のイベント ハンドラをレビューして、コードに脆弱な箇所がないことを確認してください。

Application_Start: ここに入るコードは ASP.NET のプロセス アカウントのセキュリティ コンテキストで実行され、偽装したユーザーからは実行できません。

Application_BeginRequest: ここに入るコードは ASP.NET のプロセス アカウントのセキュリティ コンテキスト、または偽装されたユーザーから実行されます。

Application_EndRequest: セキュリティで保護されたビットまたはドメインを設定するなど、出力される Cookie のプロパティを変更する必要がある場合、Application_EndRequest がその変更を行う正しい場所です。

Application_AuthenticateRequest: これはユーザー認証を行います。

Application_Error: このイベント ハンドラが呼び出されるセキュリティ コンテキストは、Windows のイベント ログに影響を与えることがあります。セキュリティ コンテキストはプロセス アカウントまたは偽装したアカウントである可能性があります。

protected void Session_End: このイベントは非決定的に開始され、セッション状態中モード専用です。

適切な承認の実行

次のレビュー項目を確認して、承認方法を確認してください。

Web サイトの制限付きアクセス領域とパブリック アクセス領域との区分
ユーザーが特定のページにアクセスできる前に Web アプリケーションから認証の完了を要求される場合、制限付きページは外部からアクセスできるページとは別のディレクトリに置かれていることを確認してください。このことにより、制限付きアクセス ディレクトリに SSL が要求される設定にすることができます。また、認証 Cookie が HTTP を使用した非暗号化セッションを経由しないことを確認するうえでも役立ちます。

制限付きページへのアクセスの保護方法
Windows 認証を使用する場合、ページ (またはその制限付きページが保存されているフォルダ) に NTFS 許可を設定して承認されたユーザーしかアクセスできないようにします。

<authorization> 要素を設定して、どのユーザーまたはユーザー グループが特定のページにアクセスできるかを指定します。

ページ クラスへのアクセスの保護方法
プリンシパル アクセス許可要求をクラスに追加して、どのユーザーまたはユーザー グループが特定のページにアクセスできるかを決定します。

Server.Transfer の使用
ユーザーを別のページへ移す際に Server.Transfer を使用する場合、現在認証されているユーザーがその別のページへのアクセス承認を確実に受けることを確認してください。ユーザーが表示許可の承認を受けていないページへの移動に Server.Transfer を使用すると、そのページは処理中になります。

Server.Transfer は、サーバーから別の要求を行って承認を強制するではなく、異なるモジュールを使用してそのページを処理します。移動先の Web ページでセキュリティが重視される場合、Server.Transfer を使用しないでください。代わりに HttpResponse.Redirect を使用してください。

Web サービス

ASP.NET Web サービスは、ASP.NET Web アプリケーションと多くの機能を共有しています。最初に、「ASP.NET のページおよびコントロール」セクションのレビュー項目を使用して Web サービスをレビューし、以下の Web サービス固有のレビュー項目を確認してください。ここで説明した問題の詳細については、モジュール 12「セキュリティ保護された Web サービスを構築する」を参照してください。

制限付きの操作またはデータの公開

呼び出し元の承認方法

権限による操作の制限

カスタム認証の使用

すべての入力の検証

SOAP ヘッダの検証

制限付きの操作またはデータの公開

Web サービスが制限付きの操作またはデータを公開する場合、そのサービスが呼び出し元の認証を行うことを確認してください。NTLM、Kerberos、基本認証、クライアントの X.509 認証などのプラットフォーム認証のメカニズムを利用するか、または SOAP ヘッダに認証トークンを渡すことができます。

認証トークンを渡す場合、WSE (Web Services Enhancements) を使用して、新しい WS-Security 仕様に準拠した方法で SOAP ヘッダを使用することができます。

呼び出し元の承認方法

.NET Framework (URL 承認、ファイル承認、.NET ロールなど)、あるいはファイル ACL などのプラットフォーム オプションによって提供される適切な承認方式を選択します。

権限による操作の制限

コード アクセス セキュリティ ポリシーの信頼レベルにより、Web サービスがアクセスできるリソースの型が決定されます。Machine.config または Web.config. の <customErrors> 要素設定を確認してください。

カスタム認証の使用

自分自身の認証方式を作成する代わりに、WSE (Web Service Enhancements) によって提供される機能を使用してください。

すべての入力の検証

外部に公開された Web メソッドが信頼範囲外のソースから入力を受け取った場合、その入力を使用または下流のコンポーネントやデータベースに渡す前に、入力パラメータをすべて検証することを確認してください。

SOAP ヘッダの検証

アプリケーションでカスタム SOAP ヘッダを使用する場合、その情報が不正操作またはリプレイされたものではないことを確認します。不正操作されていないことを保障するため、ヘッダ情報をデジタル署名してください。WSE を使用すると、標準的な方法での Web サービス メッセージのサインに役立ちます。

SoapException および SoapHeaderException オブジェクトがエラーを正しく処理し、クライアントに必要最小限の情報を提供するために使用されていることを確認してください。トラブルシューティングで使用するため、例外が適切にログ出力されていることを確認してください。

サービス対象のコンポーネント

ここでは、Enterprise Services アプリケーション内で使用されるサービス対象のコンポーネントをレビューする際に、考慮する必要がある重要レビュー ポイントを説明します。ここで説明した問題の詳細については、モジュール 11「セキュリティ保護されたサービス コンポーネントを構築する」を参照してください。

アセンブリ レベルのメタデータの使用

匿名アクセスの防御

制限付きの偽装レベルの使用

ロール ベースのセキュリティの使用

メソッド レベルの承認の使用

オブジェクト コンストラクタ文字列の使用

中間層の監査

アセンブリ レベルのメタデータの使用

アセンブリ レベルのメタデータを使用して Enterprise Services のセキュリティ設定を定義していることを確認してください。assemblyinfo.cs ファイルおよび属性を使用して、認証および承認の設定を定義します。これは、管理する際に設定が正しく確立されていることを確実にするうえで役立ちます。管理者はこれらの設定をオーバーライドできますが、オーバーライドを通じて、管理者はどのような設定が期待されているかを明確に把握することができます。

匿名アクセスの防御

コードが、ApplicationAccessControl 属性を使用して認証レベルを指定していることを確認してください。文字列 AuthenticationOption で検索を行い、関連する属性を確認してください。呼び出しレベル以上の認証が使用され、コンポーネントへのそれぞれの呼び出しの認証を保障していることを確認してください。

[assembly:ApplicationAccessControl(
Authentication = AuthenticationOption.Call)]

制限付きの偽装レベルの使用

サービス対象のコンポーネントに対して定義した偽装レベルが、通信対象のすべてのリモート サーバーの偽装レベルを決定します。文字列 ImpersonationLevel を検索して、コードがそのレベルを設定していることを確認してください。

[assembly:ApplicationAccessControl(
ImpersonationLevel=ImpersonationLevelOption.Identify)]

リモート サーバーに必要な、最も厳しい制限付きレベルの設定したことを確認してください。たとえば、サーバーが認証目的でユーザーを識別する必要があるが偽装する必要はない場合、上に示した識別レベルを使用してください。Windows 2000 ではセキュリティ コンテキストがコンピュータからコンピュータへと渡される回数に制限がないため、委任レベルの偽装は注意して適用してください。Windows Server™ 2003 は制限付き委任を導入しています。

注: Windows Server 2003 および Windows 2000 Service Pack 4 以降では、偽装権限はすべてのユーザーに与えられていません。

コンポーネントがサーバー アプリケーション内にあり、Enterprise Services に登録されている場合、上記のアセンブリ レベル属性がコンポーネントの初期設定を制御します。

コンポーネントがライブラリ アプリケーション内にある場合、クライアントの処理が偽装レベルを決定します。クライアントが ASP.NET Web アプリケーションの場合、Machine.config ファイルの <processModel> 要素で comImpersonationLevel 設定を確認してください。

ロール ベースのセキュリティの使用

コードがロール ベースのセキュリティを正しく使用し、権限のないアクセスを防いでいることを、次のレビュー項目を確認して確認してください。

ロール ベース セキュリティの有効化
ロール ベースのセキュリティが有効であることを確認してください。Windows 2000 では既定で無効になっています。コードに以下の属性が含まれていることを確認してください。

[assembly:ApplicationAccessControl(true)]

コンポーネント レベルのアクセス確認の使用
インターフェイス、コンポーネント、またはメソッド レベルで使用される場合、COM+ ロールは最も効果的であり、アプリケーションへのアクセスを制限するためだけに使用される訳ではありません。コードに以下の属性が含まれていることを確認してください。

[assembly:ApplicationAccessControl(AccessChecksLevel= 
AccessChecksLevelOption.ApplicationComponent)]

各クラスが以下のように ComponentAccessControl 属性に設定されていることも確認してください。

[ComponentAccessControl(true)]
public class YourServicedComponent :ServicedComponent
{
}

コードのロール チェックの実行
メソッド コードが ContextUtil.IsCallerInRole を呼び出す場合、これらの呼び出しが ContextUtil.IsSecurityEnabled への呼び出しの前に行われていることを確認してください。セキュリティが有効になっていない場合、IsCallerInRole は常に true を返します。セキュリティが有効になっていない場合、コードがセキュリティ例外を返すことを確認してください。

オブジェクト コンストラクタ文字列の使用

文字列 ConstructionEnabled でコードを検索して、オブジェクト コンストラクタ文字列を使用するクラスを確認してください。

[ConstructionEnabled(Default="")]
public class YourServicedComponent :ServicedComponent, ISomeInterface

オブジェクト コンストラクタ文字列を使用している場合、次のレビュー項目を確認してください。

機密情報のコンストラクタ文字列への格納
接続文字列のようなデータを格納する場合、そのデータが COM+ カタログに格納される前に暗号化されることを確認してください。データが Construct メソッドを介してコンポーネントに渡されたとき、コードはそのデータを復号する必要があります。

既定のコンストラクション文字列の提供
データが少しでも機密である場合、これは行わないでください。

中間層の監査

分散アプリケーションの層についても監査を行う必要があります。サービス コンポーネントが操作とトランザクションをログで記録していることを確認してください。呼び出し元のオリジナル ID は SecurityCallContext オブジェクトを通じて入手できます。これは、アプリケーションのセキュリティ レベルが、以下の属性を使用してプロセス レベルおよびコンポーネント レベルのチェック用に構成されている場合にのみ、入手可能です。

[assembly:ApplicationAccessControl(AccessChecksLevel= 
AccessChecksLevelOption.ApplicationComponent)]

Remoting

ここでは、.NET Remoting を使用するコードをレビューする際に考慮する必要がある重要レビュー ポイントを説明します。ここで説明した問題の詳細については、モジュール 13「セキュリティ保護されたリモート コンポーネントを構築する」を参照してください。

オブジェクトのパラメータとしての引き渡し

カスタム認証とプリンシパル オブジェクトの使用

プロキシの資格情報の設定方法

オブジェクトのパラメータとしての引き渡し

TcpChannel を使用していてコンポーネント API がカスタム オブジェクト パラメータを受け取る場合、またはカスタム オブジェクトがコンテキストの呼び出しによって渡される場合、コードには 2 つのセキュリティ脆弱性が存在します。

System.MarshalByRefObject から派生したパラメータとして渡されるオブジェクトの場合、オブジェクト参照によって渡されます。この場合、オブジェクトは URL を要求して、クライアントへのコール バックをサポートします。クライアントの URL がスプーフィングされ、別のコンピュータにコール バックしてしまう可能性があります。

シリアル化をサポートするパラメータとして渡されるオブジェクトの場合、データ値で渡されます。この場合、悪意のあるデータの挿入を防ぐため、パラメータがサーバーで逆シリアル化される際の各フィールド項目を、コードが検証することを確認してください。

カスタム オブジェクトがリモート コンポーネントにオブジェクト参照、またはデータ値で渡されることを防ぐために、サーバー側のフォーマッタ チャネル シンクの TypeFilterLevel プロパティを TypeFilterLevel.Low に設定してください。

呼び出しコンテキストで渡されるオブジェクトを見つけるには、文字列 IlogicalThreadAffinative で検索してください。このインターフェイスを実装しているオブジェクトだけが、呼び出しコンテキストに渡されることができます。

カスタム認証とプリンシパル オブジェクトの使用

カスタム認証を使用する場合、クライアントから渡されるプリンシパル オブジェクトに依存していますか。悪意のあるコードが、権限を格上げする拡張ロールを含むプリンシパル オブジェクトを作成する可能性があるため、これは潜在的に危険です。このアプローチを使用する場合、コンポーネントに接続できるクライアント コンピュータを制限する IPSec ポリシーなどの帯域外メカニズムと共に使用しているだけであることを確認してください。

プロキシの資格情報の設定方法

リモート プロキシでクライアント コードがどのように資格情報を設定しているかをレビューしてください。明示的な資格情報が使用されている場合の保管場所を確認します。これらの資格情報は、制限付きレジストリ キーなどのセキュリティで保護された場所に暗号化した上で格納する必要があります。プレーンテキストのままハードコードしないでください。クライアント コードがクライアント プロセス トークンおよび既定の資格情報を使用することが理想的です。

データ アクセス コード

ここでは、データ アクセス コードのレビューの際に考慮する必要がある重要レビュー ポイントを説明します。ここで説明した問題の詳細については、モジュール 14「セキュリティ保護されたデータ アクセスを構築する」を参照してください。

SQL インジェクションの防御

Windows 認証の使用

セキュリティで保護されたデータベース接続文字列の使用

認証されていないコードの制限方法

データベースの機密情報のセキュリティによる保護方法

ADO .NET 例外の処理

データベース接続の切断

SQL インジェクションの防御

入力を検証し、最小限の権限によるアカウントを使用してデータベースに接続し、またパラメータ化ストアド プロシージャまたはパラメータ化 SQL コマンドを使用することによって、SQL インジェクションを防いでいることを確認してください。詳細については、このモジュールの「SQL インジェクション」を参照してください。

Windows 認証の使用

Windows 認証を使用すると、ネットワーク経由でデータベース サーバーに資格情報を渡す必要がなくなり、接続文字列にユーザー名やパスワードが含まれなくなります。Windows 認証接続文字列では、以下の例に示すように Trusted_Connection='Yes' または Integrated Security='SSPI' のいずれかが使用されます。

"server='YourServer'; database='YourDatabase' Trusted_Connection='Yes'"
"server='YourServer'; database='YourDatabase' Integrated Security='SSPI'"

セキュリティで保護されたデータベース接続文字列の使用

コードが正しいこと、およびデータベース接続文字列をセキュリティで保護して使用していることをレビューしてください。ユーザー名やパスワードが含まれる場合は特に、これらの接続文字列をハードコードしたり、設定ファイルにプレーンテキストで格納しないでください。

ADO .NET 接続オブジェクトの場合は文字列 Connection で検索して、ConnectionString プロパティがどのように設定されているかをレビューしてください。

接続文字列の暗号化
コードが、暗号化された接続文字列を取り出してから復号していることを確認してください。キーの管理問題を回避するために、コードの暗号化には DPAPI を使用する必要があります。

ブランク パスワードの使用
これはしないでください。すべての SQL アカウントが強固なパスワードを持っていることを確認してください。

SA アカウントなどの高い権限を持つアカウントの使用
SA アカウント、sysadmin のメンバ、db_owner ロールなどの高い権限を持つアカウントを使用しないでください。これはよくある間違いです。データベースへのアクセス許可に制限のある、最小限の権限によるアカウントを使用していることを確認してください。

Persist Security Info の使用
ユーザー名やパスワードなどの機密情報が開通した接続から取得できるようになるため、Persist Security Info 属性が true または yes に設定されていないことを確認してください。

認証されていないコードの制限方法

データ アクセス クラス ライブラリに書き込む場合、承認されていないコードのライブラリへのアクセスによるデータベースへのアクセスを防御方法を確認します。1 つのアプローチは、StrongNameIdentityPermission 要求を使用して、呼び出しコードを特定の強固な名前を持つ秘密キーで署名されたコードにのみ制限することです。

データベースの機密情報のセキュリティによる保護方法

クレジット カード番号などの機密データをデータベースに格納する場合の、データのセキュリティでの保護方法を確認します。3DES などの強固な対称暗号化を使用して暗号化されていることを確認する必要があります。

3DES を使用して暗号化する場合、3DES 暗号化キーのセキュリティでの保護方法を確認します。DPAPI を使用して3DES 暗号化キーを暗号化し、その暗号化キーをレジストリなどの制限付きの場所に格納する必要があります。

ADO .NET 例外の処理

すべてのデータ アクセス コードが try/catch ブロック内にあり、使用する ADO .NET データ プロバイダに応じて、SqlExceptions、OleDbExceptions、または OdbcExceptions をコードが処理することを確認してください。

データベース接続の切断

例外が発生するなどデータベース接続が開いたままの場合にも、コードが脆弱でないことを確認してください。コードが finally ブロック内で接続を閉じるか、あるいは接続オブジェクトが以下に示すように using ステートメントを使用して C# 内部に構築されていることを確認してください。これは、接続が閉じていることを自動的に保障します。

using ((SqlConnection conn = new SqlConnection(connString)))
{
conn.Open();
//接続は次の場合に閉じます。例外が発生、またはコントロール フローが
// using ステートメントのスコープを normally のままにする場合。
}

要約

セキュリティ コード レビューは、セキュリティの脆弱性につながるコーディングの短所の識別に重点を置いていることを除くと、通常のコード レビューや検査に似ています。付加価値として、セキュリティの短所が除かれたコードの多くは、より堅牢になります。

このモジュールでは、XSS、SQL インジェクション、バッファ オーバーフローなどの最重要セキュリティ問題に関するマネージ コードのレビュー方法について説明しました。セキュリティの脆弱性や攻撃が成功することにつながる、その他の細かい短所の識別方法についても説明されています。

セキュリティ コード レビューは万能薬ではありません。しかし、非常に効果的であり、開発ライフ サイクル内の定期的なマイルストーンとして位置付けされる必要があります。

関連情報

詳細については、MSDN の「.NET Framework のための安全なコーディング ガイドライン」を参照してください。


表示:
© 2014 Microsoft