コード レビュー
トピック
モジュールの内容
セキュリティ コード レビューは、セキュリティ問題およびインシデントの原因となりうるセキュリティで保護されていないコーディングや脆弱性の識別に重点を置きます。コード レビューには時間がかかりますが、開発段階でセキュリティの短所修正に要する労力およびコストは、その後の製品展開や保守サイクルで要する労力およびコストに比べてはるかに少ないため、プロジェクト開発サイクルの定期的なイベントとして行う必要があります。
このモジュールは、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 部のセキュリティ保護に関するモジュールを使用します。このモジュールで概説するレビュー項目の詳細については、これらのモジュールを参照してください。
| ||||||||||||||||||
| • | 次の関連チェックリストも使用します。
|
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
script:alert('hello');">
<IMG SRC="java
script:alert('hello');">
<style> タグも、以下に示すように MIME タイプを変更させることにより、挿入のソースとなることがあります。
<style TYPE="text/javascript">
alert('hello');
</style>
危険なことが分かっている文字をフィルタして、コードが入力のサニタイジングを試みるかどうかを確認します。一般的に、悪意のあるユーザーは検証をバイパスできる別の表記を見つけるため、このアプローチに依存しないでください。このアプローチに依存する代わりに、セキュリティで保護された安全な既知の入力をコードが検証できるようにする必要があります。表 21.2 に、一般的な文字を表記するさまざまな方法が示されています。
表 21.2: 文字表記
| 文字 | 10 進 | 16 進 | HTML 文字セット | Unicode |
| " (二重引用符) | " | " | " | \u0022 |
| ' (一重引用符) | ' | ' | ' | \u0027 |
| & (アンパサンド) | & | & | & | \u0026 |
| < (小なり) | < | < | < | \u003c |
| > (大なり) | > | > | > | \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. | データベースにアクセスするコードを確認します。 |
| 2. | コードにパラメータ化ストアド プロシージャが使用されているかどうかを確認します。 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 ステートメントのパラメータが使用されていることを確認します。 select status from Users where UserName=@userName 以下のアプローチが、入力が直接文字列連結に利用され、実行可能な SQL ステートメントを構築している箇所で使用されていないことを確認します。 string sql = "select status from Users where UserName='" + txtUserName.Text + "'"; |
| 4. | コードが入力のフィルタ処理を試行するどうかを確認します。 |
バッファ オーバーフロー
バッファ オーバーフローのコード レビューでは、P/Invoke または COM Interop 層経由でアンマネージ コードを呼び出すコードを特にレビューしてください。配列がアクセスするすべての箇所で配列範囲が自動的に確認されるため、マネージ コード自体のバッファ オーバーフローに対する脆弱性はそれほど大きくありません。Win32 DLL または COM オブジェクトを呼び出したら直ちに、その API 呼び出しを慎重に検査する必要があります。
次の手順は、バッファ オーバーフローに対する脆弱性を確認するうえで役立ちます。
| 1. | アンマネージ コード呼び出し箇所を検索します。 |
| 2. | アンマネージ API に渡される文字列パラメータを確認します。 void SomeFunction( char *pszInput )
{
char szBuffer[10];
// 要注意、長さ確認が行われていません。入力はバッファへ直接コピーされます。
// 長さを確認するか、strncpy を使用する必要があります。
strcpy(szBuffer, pszInput);
. . .
}
注: strncpy はコピーされる文字数を制限するだけでコピー先に十分な領域があるかどうかの確認は行わないため、strncpy を使用してもバッファ オーバーフローが発生する場合があります。 アンマネージ コードを所有していないため検査できない場合は、意図的に長くした入力文字列や無効な引数を使用して、API を厳密にテストしてください。 |
| 3. | ファイル パスの長さを確認します。 |
| 4. | 出力文字列を確認します。 |
| 5. | 配列範囲を確認します。 |
| 6. | アンマネージ コードが /GS スイッチでコンパイルされていることを確認します。 |
マネージ コード
ここのレビュー項目を使用して、マネージ ソース コード全体を分析してください。レビュー項目はアセンブリの種類に関係なく使用することができます。ここでは、一般的なマネージ コードの脆弱性を識別するうえで役立ちます。ここで説明した問題の詳細、および脆弱性を説明したコード サンプルについては、モジュール 7「セキュリティ保護されたアセンブリを構築する」を参照してください。
マネージ コードに明示的なコード アクセス セキュリティ機能を使用している場合は、関連するレビュー ポイントについて、このモジュールの「コード アクセス セキュリティ」を参照してください。次のレビュー項目を使用すると、マネージ コードの脆弱性を識別するうえで役立ちます。
| • | クラス デザインのセキュリティ保護 |
| • | スレッドの作成 |
| • | シリアル化の使用 |
| • | リフレクションの使用 |
| • | 例外の処理 |
| • | 暗号化の使用 |
| • | 機密情報の格納 |
| • | 委任の使用 |
クラス デザインのセキュリティ保護
アセンブリは、含まれるクラスや他の型と同程度のセキュリティでしか保護されません。次のレビュー項目は、クラス デザインのセキュリティをレビューするうえで役立ちます。
| • | 型およびメンバの参照範囲の制限 |
| • | 非基底クラスのシールド設定 パブリックな基底クラスについては、コード アクセス セキュリティの継承要求を使用して、クラスから継承できるコードに制限することができます。これは、重層的な防御に有効です。 |
| • | フィールドの公開に対するプロパティの使用 |
| • | 読み取り専用プロパティの使用 |
| • | 仮想内部メソッドの使用 |
| • | IDisposable の実装 |
スレッド の作成
マルチスレッド コードは、見つけにくいタイミング関連のバグまたはセキュリティの脆弱性の原因となりうる競合を引き起こしやすいコードです。マルチスレッド コードの場所を確認するには、以下のコード フラグメントに示すようにソース コードを「Tread」で検索して、新しい Tread オブジェクトが作成された場所を識別してください。
Thread t = new Thread(new ThreadStart(someObject.SomeThreadStartMethod));
次のレビュー項目を使用すると、スレッドの脆弱性を識別するうえで役立ちます。
| • | コードによるセキュリティ チェックの結果のキャッシュ |
| • | コードの偽装 |
| • | コードにおける静的クラス
コンストラクタ |
| • | Dispose メソッドの同期 |
シリアル化の使用
シリアル化をサポートするクラスは SerializableAttribute に指定されるか、あるいは Iserializable から派生します。シリアル化をサポートするクラスは、文字列 Serializable のテキスト検索によって見つけることができます。次に、以下の問題についてコードをレビューします。
| • | クラスでの機密性の高いデータの含有 クラスが機密性の高いデータをシリアル化する必要がある場合、データの保護方法についてレビューします。まずデータの暗号化を検討します。 |
| • | クラスへの Iserializable の実装 |
| • | クラスによるデータ ストリームの検証 |
リフレクションの使用
リフレクションを使用するコードを確認するには、リフレクション型を含む名前空間の "System.Reflection" で検索を行います。リフレクションを使用する場合、次のレビュー項目を確認すると、潜在的な脆弱性を識別するうえで役立ちます。
| • | アセンブリの動的な読み込み |
| • | ランタイムでの動的なコードの作成 |
| • | 他の型に対するリフレクションの使用 |
例外の処理
セキュリティで保護された例外処理は、堅牢なコードに必要です。例外の詳細なログを確実に記録して問題の診断に役立て、内部システムの詳細がクライアントに公開されるのを確実に防ぎます。次のレビュー項目を確認すると、例外処理の脆弱性を識別するうえで役立ちます。
| • | 初期段階での障害の発生 |
| • | 例外の処理方法 |
| • | 例外の詳細のログ記録 |
| • | 例外フィルタの使用 例外フィルタの脆弱性の例については、モジュール 7「セキュリティ保護されたアセンブリを構築する」の「例外管理」を参照してください。 |
暗号化の使用
使用する場合は、コードが自身の暗号化ルーチンを実装していないことを確認します。暗号化ルーチンを実装する代わりに、名前空間 System.Security.Cryptography、あるいはデータ保護 API (DPAPI) などの Win32 暗号化を使用する必要があります。次のレビュー項目を確認すると、潜在的な暗号化関連の脆弱性を識別するうえで役立ちます。
| • | 対称暗号化の使用 |
| • | 最大サイズのキーの使用 |
| • | ハッシュの使用 |
| • | 暗号化のための乱数の生成 |
機密情報の格納
アセンブリが機密情報を格納する場合、デザインをレビューして機密情報の格納が絶対必要であることを確認します。機密情報を格納する必要がある場合、次のレビュー項目を確認してできるだけセキュリティで保護してください。
| • | 機密情報のメモリへの保存 |
| • | プレーンテキストのパスワードまたは SQL 接続文字列の、Web.config または Machine.config
への保存 |
| • | 機密情報を暗号化する方法 |
| • | 機密情報のレジストリへの保存 |
| • | リバース
エンジニアリングの問題 注: 機密データの隠蔽を暗号化ツールに依存しないでください。暗号化ツールを使用すると機密データの識別がより困難になりますが、問題は解決されません。 |
委任の使用
どのコードも、メソッドと委任を関連付けることができます。委任には、低い信頼レベルで実行される潜在的に悪意のあるコードも含まれます。
| • | 信頼関係にないソースからの委任の受け取り |
| • | 委任の呼び出し前におけるアサートの使用 |
コード アクセス セキュリティ
すべてのマネージ コードに対し、コード アクセス セキュリティ許可が要求されます。問題の多くは、コードが部分的に信頼された環境で使用され、コードまたは呼び出しコードがコード アクセス セキュリティ ポリシーから十分に信頼されない場合にのみ、発生します。
ここで説明した問題の詳細については、モジュール 8「コード アクセス セキュリティの実践」を参照してください。
以下のレビュー ポイントを使用して、適切で安全なコード アクセス セキュリティが使用されていることを確認してください。
| • | 部分的に信頼された呼び出し元のサポート |
| • | パブリックな型およびメンバへのアクセスの制限 |
| • | 宣言型セキュリティの使用 |
| • | Assert の呼び出し |
| • | 必要に応じた、アクセス許可の要求の使用 |
| • | リンク確認要求の使用 |
| • | Deny または PermitOnly の使用 |
| • | 特に危険なアクセス許可の使用 |
| • | /unsafe オプションを指定したコンパイル |
部分的に信頼された呼び出し元のサポート
コードが部分的に信頼された呼び出し元をサポートする場合、攻撃される危険性が大きくなります。その結果、広範囲に渡る徹底したコード レビューを行うことが特に重要になります。Web アプリケーションの <trust> レベルが、部分的に信頼されたレベルで実行される設定になっているかどうかを確認してください。この設定になっている場合、そのアプリケーション用に開発されるアセンブリは、部分的に信頼された呼び出し元をサポートする必要があります。
次のレビュー項目を確認すると、潜在的に脆弱な領域を識別するうえで役立ちます。
| • | アセンブリに対する強固な名前付け 注: ASP.NET アプリケーションに呼び出される強固な名前のアセンブリは、グローバル アセンブリ キャッシュにインストールする必要があります。 |
| • | APTCA の使用 |
| • | オブジェクト参照の引き渡し |
パブリックな型およびメンバへのアクセスの制限
コード アクセス セキュリティ ID 要求を使用して、パブリックな型およびメンバへのアクセスを制限することができます。これは、アセンブリが攻撃を受ける危険性を減らすのに役立ちます。
| • | 呼び出し元の制限における ID 要求の使用
|
| • | サブクラスの制限に対する継承要求の使用 |
宣言型セキュリティ属性の使用
宣言型セキュリティ属性は Permview.exe. などのツールを使用して表示させることができます。これは、アセンブリの利用者および管理者がコードのセキュリティ要件を理解するうえで非常に役立ちます。
| • | 最小限のアクセス許可の要求 |
| • | 必要に応じたアクセス許可の要求、またはアクセス許可の拒否 |
| • | 宣言型セキュリティではなく強制型セキュリティの使用 |
| • | クラスとメンバのレベル属性の組み合わせ |
Assert の呼び出し
Assert 呼び出しについてコードを検索してください。この検索により Debug.Assert のインスタンスが見つかることがあります。コードがどこで CodeAccessPermission オブジェクトに Assert を呼び出すかを探します。コード アクセス許可をアサートする場合は、危険性のあるプラクティスであるスタック ウォークを要求するコード アクセス セキュリティ許可を回避してください。悪意のある呼び出し元が、セキュリティで保護されたリソースまたは権限による操作にアクセスするアサートを行えないようにするための、コードにおける処理方法を確認してください。次のレビュー項目を確認してください。
| • | Demand と Assert のパターンの使用 |
| • | Assert 呼び出しと RevertAssert 呼び出しとのマッチング |
| • | アサート時間の短縮 |
必要に応じた、アクセス許可の要求の使用
コードは常に .NET Framework クラス ライブラリからのアクセス許可の要求チェックを受けますが、コードが明示的なアクセス許可の要求を使用する場合、適切に要求されていることを確認してください。コードを文字列. Demand で検索して、宣言型または強制型のアクセス許可の要求のどちらであるかを識別し、次に次のレビュー項目を確認します。
| • | データのキャッシュ |
| • | カスタム リソースまたは権限による操作の公開 |
| • | 初期段階でのアクセス許可の要求 |
| • | 冗長アクセス要求の発行 |
リンク確認要求の使用
一般的な確認要求とは異なり、リンク確認要求はコードの直接の呼び出し元だけをチェックします。完全なスタック ウォークは実行されないため、リンク確認要求を使用するコードはおとり攻撃にさらされます。おとり攻撃の詳細については、モジュール 8「コード アクセス セキュリティの実践」を参照してください。
コードを文字列 .LinkDemand で検索し、リンク確認要求が使用されている箇所を識別してください。これらは宣言的にのみ使用されます。一例を以下のコード フラグメントに示します。
[StrongNameIdentityPermission(SecurityAction.LinkDemand,
PublicKey="00240000048...97e85d098615")]
public static void SomeOperation() {}
ここで説明した問題の詳細については、モジュール 8「コード アクセス セキュリティの実践」の「リンク要求」を参照してください。次のレビュー項目は、コードのリンク確認要求の使用法についてレビューするうえで役立ちます。
| • | リンク確認要求使用の理由 |
| • | 呼び出し元の信頼性 |
| • | リンク確認要求での保護されたコードの呼び出し |
| • | メソッドおよびクラス
レベルでのリンク確認要求の使用 |
| • | シールされていないクラスでリンク確認要求の使用 |
| • | 構造の保護に対するリンク確認要求の使用 |
| • | 明示的なインターフェイスの使用 |
潜在的に危険なアクセス許可の使用
以下のアクセス許可型が信頼できるコードにのみ付与されていることを確認してください。これらのほとんどは独自のアクセス許可型を持たず、一般的な 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 の使用 注: SupressUnmanagedCodeSecurityAttribute を適用すると、Interop 層からの暗黙的な UnmanagedCode アクセス許可の要求が、LinkDemand に変更されます。つまり、コードがおとり攻撃に対して脆弱になります。 | ||||||||||||
| • | アンマネージ エントリ ポイントの公開 | ||||||||||||
| • | バッファ オーバーフローに対する防御 注: C および C++ に適用されるコード レビュー ルールと統制すべてがアンマネージ コードに適用されます。 | ||||||||||||
| • | 列挙型の範囲の確認 | ||||||||||||
| • | アンマネージ コード メソッド用の名前付け規則の使用 | ||||||||||||
| • | 潜在的に危険な API の呼び出しの確認
|
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 の呼び出し try
{
string mappedPath = Request.MapPath( inputPath.Text,
Request.ApplicationPath, false);
}
catch (HttpException)
{
// クロス アプリケーション マッピングを実行しようとしました。
} 詳細については、モジュール 10「セキュリティ保護された ASP.NET ページとコントロールを構築する」の「MapPath を使用する」を参照してください。 |
| • | データ型の検証方法 |
| • | 文字列型の検証方法 |
| • | 検証コントロールの使用 |
| • | クライアント側の検証への依存 |
XSS 攻撃に対する脆弱性
XSS に対する脆弱性について、必ず Web ページをレビューしてください。詳細については、このモジュールの「クロスサイト スクリプティング」を参照してください。
クエリ文字列と Cookie の入力の検証
コードが、URL クエリ文字列から渡された入力フィールドおよび Cookie から抽出された入力フィールドを検証することを確認してください。以下のテキスト文字列を検索して、脆弱なコードを見つけます。
| • | Request.QueryString |
| • | Request.Cookies |
入力値の型、範囲、フォーマット、および長さが、型付けされたオブジェクトおよび正規表現を使用して、フォーム フィールドに対してと同様に検証されることを確認してください (前述した「フォーム フィールド入力の検証」を参照してください)。無効なコンストラクトを打ち消してしまうと XSS バグにつながるおそれがあるため、ユーザー入力から派生するすべての HTML や URL エンコード出力についても考慮してください。
ビュー ステートのセキュリティ保護
アプリケーションがビュー ステートを使用する場合、不正操作は防止されているかどうかを確認します。次のレビュー項目を確認してください。
| • | アプリケーション レベルでのビュー ステート保護の有効化 <pages enableViewState="true" enableViewStateMac="true" /> |
| • | ページ単位でのビュー ステート保護のオーバーライド |
| • | コードのビュー ステート保護のオーバーライド |
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 サイトの制限付きアクセス領域とパブリック
アクセス領域との区分 |
| • | 制限付きページへのアクセスの保護方法 <authorization> 要素を設定して、どのユーザーまたはユーザー グループが特定のページにアクセスできるかを指定します。 |
| • | ページ クラスへのアクセスの保護方法 |
| • | 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 設定を確認してください。
ロール ベースのセキュリティの使用
コードがロール ベースのセキュリティを正しく使用し、権限のないアクセスを防いでいることを、次のレビュー項目を確認して確認してください。
| • | ロール ベース セキュリティの有効化 [assembly:ApplicationAccessControl(true)] |
| • | コンポーネント レベルのアクセス確認の使用 [assembly:ApplicationAccessControl(AccessChecksLevel= AccessChecksLevelOption.ApplicationComponent)] 各クラスが以下のように ComponentAccessControl 属性に設定されていることも確認してください。 [ComponentAccessControl(true)]
public class YourServicedComponent :ServicedComponent
{
} |
| • | コードのロール チェックの実行 |
オブジェクト コンストラクタ文字列の使用
文字列 ConstructionEnabled でコードを検索して、オブジェクト コンストラクタ文字列を使用するクラスを確認してください。
[ConstructionEnabled(Default="")] public class YourServicedComponent :ServicedComponent, ISomeInterface
オブジェクト コンストラクタ文字列を使用している場合、次のレビュー項目を確認してください。
| • | 機密情報のコンストラクタ文字列への格納 |
| • | 既定のコンストラクション文字列の提供 |
中間層の監査
分散アプリケーションの層についても監査を行う必要があります。サービス コンポーネントが操作とトランザクションをログで記録していることを確認してください。呼び出し元のオリジナル 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 プロパティがどのように設定されているかをレビューしてください。
| • | 接続文字列の暗号化 |
| • | ブランク パスワードの使用 |
| • | SA アカウントなどの高い権限を持つアカウントの使用 |
| • | Persist Security Info
の使用 |
認証されていないコードの制限方法
データ アクセス クラス ライブラリに書き込む場合、承認されていないコードのライブラリへのアクセスによるデータベースへのアクセスを防御方法を確認します。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 のための安全なコーディング ガイドライン」を参照してください。