セキュリティ フレーム:例外管理 | 対応策

製品/サービス [アーティクル]
WCF
Web API
Web アプリケーション

WCF- serviceDebug ノードを構成ファイルに含めない

タイトル 詳細
コンポーネント WCF
SDL フェーズ Build
適用できるテクノロジ ジェネリック、NET Framework 3
属性 該当なし
参照 MSDNFortify Kingdom
手順 Windows Communication Framework (WCF) サービスでは、デバッグ情報を公開する構成が可能です。 デバッグ情報は、運用環境では使用しないようにしてください。 <serviceDebug> タグにより、WCF サービスでデバッグ情報機能を有効にするかどうかが定義されます。 includeExceptionDetailInFaults 属性が true に設定されている場合、アプリケーションからの例外情報はクライアントに返されます。 攻撃者は、デバッグ出力から入手した追加の情報を使用して、アプリケーションが使用するフレームワーク、データベース、その他のリソースを対象とした攻撃をマウントすることができます。

次の構成ファイルには、<serviceDebug> タグが含まれています。

<configuration> 
<system.serviceModel> 
<behaviors> 
<serviceBehaviors> 
<behavior name=""MyServiceBehavior""> 
<serviceDebug includeExceptionDetailInFaults=""True"" httpHelpPageEnabled=""True""/> 
... 

サービスのデバッグ情報を無効にします。 これは、アプリケーションの構成ファイルから <serviceDebug> タグを削除することで実行できます。

WCF- serviceMetadata ノードを構成ファイルに含めない

タイトル 詳細
コンポーネント WCF
SDL フェーズ Build
適用できるテクノロジ ジェネリック
属性 ジェネリック、NET Framework 3
参照 MSDNFortify Kingdom
手順 サービスに関する情報を公開すると、サービスの悪用について攻撃者に多くの洞察を与えてしまう可能性があります。 <serviceMetadata> タグにより、メタデータの公開機能が有効化されます。 サービス メタデータには、パブリックにアクセスできないようにする必要がある機密情報が含まれている可能性があります。 少なくとも、信頼されたユーザーにのみメタデータへのアクセスを許可し、不要な情報は公開されないことを確認してください。 メタデータを公開する機能をすべて無効にすると、より安全です。 安全な WCF 構成には <serviceMetadata> タグが含まれません。

ASP.NET Web API で適切な例外処理が実行されたことを確認する

タイトル 詳細
コンポーネント Web API
SDL フェーズ Build
適用できるテクノロジ MVC 5、MVC 6
属性 該当なし
参照 ASP.NET Web API での例外処理ASP.NET Web API でのモデル検証
手順 既定では、ASP.NET Web API でキャッチされなかったほとんどの例外が、状態コード 500, Internal Server Error を伴った HTTP 応答に変換されます。

API によって返されるこれらの状態コードを制御するために、次に示すように HttpResponseException を使用することができます。

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item;
}

例外の応答でさらなる制御を行うために、次に示すように HttpResponseMessage クラスを使用することができます。

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
        {
            Content = new StringContent(string.Format("No product with ID = {0}", id)),
            ReasonPhrase = "Product ID Not Found"
        }
        throw new HttpResponseException(resp);
    }
    return item;
}

HttpResponseException 型ではない、ハンドルされない例外をキャッチするには、例外フィルターを使用できます。 例外フィルターは System.Web.Http.Filters.IExceptionFilter インターフェイスを実装します。 例外フィルターを記述する最も簡単な方法は、System.Web.Http.Filters.ExceptionFilterAttribute クラスから派生させ、OnException メソッドをオーバーライドすることです。

NotImplementedException 例外を HTTP 状態コード 501, Not Implemented に変換するフィルターを次に示します。

namespace ProductStore.Filters
{
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http.Filters;

    public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute 
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            if (context.Exception is NotImplementedException)
            {
                context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
            }
        }
    }
}

Web API 例外フィルターを登録する方法はいくつかあります。

  • アクションごと
  • コントローラーごと
  • グローバル

特定のアクションにフィルターを適用するには、フィルターをアクションに属性として追加します。

public class ProductsController : ApiController
{
    [NotImplExceptionFilter]
    public Contact GetContact(int id)
    {
        throw new NotImplementedException("This method is not implemented");
    }
}

controller のすべてのアクションにフィルターを適用するには、フィルターを controller クラスに属性として追加します。

[NotImplExceptionFilter]
public class ProductsController : ApiController
{
    // ...
}

すべての Web API コントローラーにグローバルにフィルターを適用するには、フィルターのインスタンスを GlobalConfiguration.Configuration.Filters コレクションに追加します。 このコレクション内の例外フィルターは、任意の Web API コントローラー アクションに適用されます。

GlobalConfiguration.Configuration.Filters.Add(
    new ProductStore.NotImplExceptionFilterAttribute());

モデルの検証のために、モデルの状態を次のように CreateErrorResponse メソッドに渡すことができます。

public HttpResponseMessage PostProduct(Product item)
{
    if (!ModelState.IsValid)
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
    }
    // Implementation not shown...
}

ASP.NET Web API での例外処理とモデルの検証の詳細については、「参照」セクションのリンクを参照してください。

エラー メッセージ内のセキュリティの詳細を公開しない

タイトル 詳細
コンポーネント Web アプリケーション
SDL フェーズ Build
適用できるテクノロジ ジェネリック
属性 該当なし
参照 該当なし
手順

一般的なエラー メッセージは、機密性の高いアプリケーション データを含まずに、ユーザーに直接提供されます。 機密データの例は次のとおりです。

  • サーバー名
  • Connection strings
  • ユーザー名
  • パスワード
  • SQL プロシージャ
  • 動的 SQL エラーの詳細
  • スタック トレースとコード行
  • メモリに格納された変数
  • ドライブとフォルダーの場所
  • アプリケーションのインストール ポイント
  • ホスト構成設定
  • その他の内部アプリケーションの詳細

IIS 内でのカスタム エラーを有効にするだけでなく、アプリケーション内のすべてのエラーをトラップし、一般的なエラー メッセージを提供すると、情報漏えいを防ぐことができます。 SQL Server データベースと .NET の例外処理は、その他のエラー処理アーキテクチャの中でも特に詳細であり、アプリケーションをプロファイリングする悪意のあるユーザーにとっては非常に便利なものです。 .NET 例外クラスから派生するクラスの内容は、直接表示しないでください。また、予期しない例外がユーザーに誤って直接表示されることがないように、適切な例外処理が行われることを確認してください。

  • 例外またはエラーのメッセージで直接検出される特定の詳細情報を除いた、一般的なエラー メッセージをユーザーに直接提供します。
  • .NET 例外クラスの内容をユーザーに直接表示しないでください。
  • すべてのエラー メッセージをトラップし、適切な場合はアプリケーション クライアントに送信される一般的なエラー メッセージを使用して、ユーザーに通知します。
  • 例外クラスの内容、特に .ToString() からの戻り値あるいは Message または StackTrace プロパティの値をユーザーに直接公開しないでください。 この情報は安全な方法でログ記録し、ユーザーにはより当たり障りのメッセージを表示します。

既定のエラー処理ページを実装する

タイトル 詳細
コンポーネント Web アプリケーション
SDL フェーズ Build
適用できるテクノロジ ジェネリック
属性 該当なし
参照 ASP.NET エラー ページ設定の編集ダイアログ ボックス
手順

ASP.NET アプリケーションでエラーが生じ、HTTP/1.x 500 内部サーバー エラーが発生した場合、または機能構成 (要求フィルターなど) が原因でページが表示されない場合、エラー メッセージが生成されます。 管理者は、アプリケーションでクライアントにわかりやすいメッセージを表示するか、クライアントに詳細なエラー メッセージを表示するか、localhost のみに詳細なエラー メッセージを表示するかを選択できます。 web.config 内の <customErrors> タグには 3 つのモードがあります。

  • On: カスタム エラーが有効になるように指定します。 defaultRedirect 属性が指定されていない場合、ユーザーには一般的なエラーが表示されます。 リモート クライアントとローカル ホストにカスタム エラーが表示されます。
  • Off: カスタム エラーが無効になるように指定します。 リモート クライアントとローカル ホストに詳細な ASP.NET エラーが表示されます。
  • RemoteOnly: カスタム エラーがリモート クライアントにのみ表示されることと、ASP.NET エラーがローカル ホストにのみ表示されることを指定します。 これは、既定値です。

アプリケーション/サイトの web.config ファイルを開き、タグに <customErrors mode="RemoteOnly" /> または <customErrors mode="On" /> が定義されていることを確認します。

IIS の deployment メソッドを retail に設定する

タイトル 詳細
コンポーネント Web アプリケーション
SDL フェーズ デプロイ
適用できるテクノロジ ジェネリック
属性 該当なし
参照 deployment 要素 (ASP.NET 設定スキーマ)
手順

<deployment retail> スイッチは、実稼働 IIS サーバーで使用するためのものです。 このスイッチを使用すると、ページ上にトレース出力を生成するアプリケーション機能、エンド ユーザーに詳細なエラー メッセージを表示する機能、debug スイッチが無効化され、これによりアプリケーションのパフォーマンスを最大限に高め、セキュリティ情報の漏えいの可能性を最小限に抑えながら、アプリケーションの実行が支援されます。

多くの場合、失敗した要求トレースやデバッグなどの開発者向けスイッチおよびオプションが、開発中に有効化されています。 すべての実稼働サーバーの deployment メソッドを retail に設定することをお勧めします。 machine.config ファイルを開き、<deployment retail="true" /> が true のままであることを確認します。

例外は安全に失敗する必要がある

タイトル 詳細
コンポーネント Web アプリケーション
SDL フェーズ Build
適用できるテクノロジ ジェネリック
属性 該当なし
参照 安全な失敗
手順 アプリケーションは安全に失敗する必要があります。 特定の意思決定に基づいてブール値を返すすべてのメソッドでは、例外ブロックを慎重に作成する必要があります。 十分に検討せずに例外ブロックを記述すると、セキュリティの問題が潜在する多くの論理エラーが発生します。

        public static bool ValidateDomain(string pathToValidate, Uri currentUrl)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(pathToValidate))
                {
                    var domain = RetrieveDomain(currentUrl);
                    var replyPath = new Uri(pathToValidate);
                    var replyDomain = RetrieveDomain(replyPath);

                    if (string.Compare(domain, replyDomain, StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        //// Adding additional check to enable CMS urls if they are not hosted on same domain.
                        if (!string.IsNullOrWhiteSpace(Utilities.CmsBase))
                        {
                            var cmsDomain = RetrieveDomain(new Uri(Utilities.Base.Trim()));
                            if (string.Compare(cmDomain, replyDomain, StringComparison.OrdinalIgnoreCase) != 0)
                            {
                                return false;
                            }
                            else
                            {
                                return true;
                            }
                        }

                        return false;
                    }
                }

                return true;
            }
            catch (UriFormatException ex)
            {
                LogHelper.LogException("Utilities:ValidateDomain", ex);
                return true;
            }
        }

上記のメソッドでは、何らかの例外が発生すると、常に true を返します。 エンド ユーザーが、ブラウザーでは考慮されているが Uri() コンストラクターでは考慮されていない正しくない URL を入力した場合、例外が返され、攻撃対象は、有効ではあるものの正しくない URL に誘導されます。