WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

ASP.NET 4 の要求の検証

by WebSurfer 2012年2月19日 15:13

ユーザー入力に <script> のような文字を許可するために、web.config の pages 要素または個々のページの @ Page ディレクティブで ValidateRequest="false" に設定することがあると思います。

ASP.NET 3.5 以前の場合はそれだけで <script> のような文字入力を許可できましたが、ASP.NET 4 では、それだけでは以下の画面のように HttpRequestValidationException がスローされてしまいます。

HttpRequestValidationException がスローされた

ASP.NET 4 ではセキュリティ強化のため、デフォルトで、BeginRequest の前に検証を有効にしているそうです。その結果、aspx ページ要求のみでなく、ASP.NET のすべてのリソースの要求(例えば、クッキー、Web サービスやカスタム HTTP ハンドラによる要求、カスタム HTTP モジュールが読む HTTP 要求のコンテンツ)に対して検証が適用されるとのことです。

この検証を、従前(ASP.NET 3.5 以前)の方法にするか新しい(ASP.NET 4)方法にするかを指定するために、httpRuntime 要素に新しい属性 requestValidationMode が追加されています。

この requestValidationMode が 4.0(デフォルト)に設定されている場合は、web.config の pages 要素 (存在する場合) と個々のページの @ Page ディレクティブの要求検証設定は無視されます。

そのため、requestValidationMode を設定しないとデフォルトの 4.0 になって、たとえ @ Page ディレクティブで ValidateRequest="false" に設定してあってもそれは無視され、ユーザーが <script> のような文字を POST すると例外がスローされます。

詳しくは Microsoft のホワイトペーパー ASP.NET 4 Breaking Changes の ASP.NET Request Validation のセクションおよび MSDN ライブラリの RequestValidationMode プロパティ のページを参照してください。

従って、ASP.NET 4 でユーザー入力に <script> のような文字を許可するためには、httpRuntime 要素の requestValidationMode 属性を 2.0 に設定した上で、ValidateRequest="false" に設定しなければなりません。

通常はユーザー入力のある特定のページのみ requestValidationMode="2.0" に設定したいと思いますが、そのような場合は location 要素の path 属性にそのページを指定します。以下のような感じです。

<configuration>
  <location path="133-RequestValidationMode.aspx">
    <system.web>
      <httpRuntime requestValidationMode="2.0" />
    </system.web>
  </location>
</configuration>

Tags:

Validation

Active Directory 証明書サービス

by WebSurfer 2012年2月5日 15:04

自己署名入り証明書(いわゆる、オレオレ証明書)でないサーバー証明書と、CA 証明書を Active Directory 証明書サービスを利用して発行してインストールし、接続時に警告を出さないで SSL 通信を行う方法の紹介です。

サーバーは Windows Server 2008 で、Active Directory ドメインサービスと Web サーバー (IIS) は同一サーバーにインストールし、そこに Active Directory 証明書サービス (AD CS) をエンタープライズ CA としてインストールしてあるという環境です。

(注 1)証明書を発行するサーバーと Web サーバーは別でも問題ないですが、ドメインコントローラーでないサーバーではスタンドアロン CA しかインストールできないかもしれません。(ドメインコントローラーでなくても、ドメイン環境下のサーバーであればいいのかもしれませんが、未確認です)

(注 2)AD CS をインストールする際、「役割サービスの追加」メニューで[証明機関]に加えて[証明機関 Web 登録]も追加してください。前者はデフォルトで選択されていますが、後者はユーザーが手動で選択する(チェックマークを入れる)必要があります。それをしないと、以下の 7 以降の手順でブラウザから Certsrv にアクセスしてサーバー証明書を入手することができません。

エンタープライズ CA をインストールすると、CA 証明書は自動的にそのサーバーの「信頼されたルート証明機関」と「中間証明機関」の両方にインストールされます。

さらに、クライアント PC からドメインユーザーアカウントにログオンすると、クライアント PC にも自動的に CA 証明書が「信頼されたルート証明機関」と「中間証明機関」の両方にインストールされます。

したがって、ドメイン環境下であれば、Web サーバーにサーバー証明書をインストールするだけで、接続時に警告を出さない SSL 通信を行うことが可能になります。

サーバー証明書を取得する方法は、Microsoft TechNet の HTTPS メッセージング用のサーバー証明書を取得する に詳しく書いてありますが、以下にその要点を書きます。(TechNet の日本語の記事はリンク切れになってしまいました。クリックすると英語の Obtain Server Certificates for HTTPS Messaging に飛んでしまいます)

  1. まず、CSR(Certificate Signing Request: サーバー証明書を申請・取得するために認証局へ提出する署名リクエスト)を作成します。必ずサーバー証明書をインストールする Web サーバーで作業してください。
  2. IIS マネージャーを起動し、IIS セクションの「サーバー証明書」をダブルクリックします。
  3. 「操作」セクションの「証明書の要求の作成」をクリックし、「証明書の要求」ウィザードを起動します。
  4. 「識別名プロパティ」画面でディスティングイッシュネーム(一般名など 6 項目の情報)を登録し、「次へ」ボタンをクリックします。一般名(コモンネーム)は SSL 接続の際の URL と一致させる必要があるので注意してください。
IIS マネージャーでディスティングイッシュネームの登録
  1. 次の画面の「暗号化サービス プロバイダ」ドロップダウンリストで「Microsoft RSA Schannel Cryptographic Provide」を選択し、「ビット長」ドロップダウンリストでこれから生成する公開鍵の鍵長(2048 または 1024)を選択して「次へ」をクリックします。
  2. 次の画面で、CSR を保存するフォルダ、ファイル名を入力する画面が表示されるので、任意のフォルダ、ファイル名を指定して「終了」ボタンをクリックします。これで下の画像のような CSR が作成されます(保存場所を覚えておいて下さい)。手順 2 から 6 は、Symantec(旧 Verisign)のサイト新規・追加の手続きからリングが張ってあるCSR生成手順が参考になると思います。
CSR(Certificate Signing Request) を作成
  1. 次はサーバー証明書の作成・入手です。AD CS をインストールすると(その際[証明機関]に加えて[証明機関 Web 登録]の追加も必要なので注意)、そのサーバーに IIS もインストールされ、Default Web Site 下に CertSrv という仮想ディレクトリが作成されているはずです。そこにアクセスしてサーバー証明書をダウンロードします。
  2. サーバー証明書をインストールする Web サーバーで IE を起動し、手順 7 に述べた CertSrv にアクセスします。
IE で CertSrv にアクセス
  1. IE に表示された CertSrv の画面で、「証明書を要求する」⇒「証明書の要求の詳細設定」⇒「Base 64 エンコード CMC または PKCS #10 ファイルを使用して証明書の要求を送信するか、または Base 64 エンコード PKCS #7 ファイルを使用して更新の要求を送信する。」の順にクリックして画面遷移していきます。
  2. 手順 6 で取得した CSR を開き、そのファイルの内容を「証明書の要求または更新要求の送信」ページの「保存された要求:」ボックスにコピー&ペーストします。「証明書テンプレート:」のドロップダウンリストで「Web サーバー」を選択し、「追加属性」を指定して「送信」ボタンをクリックします。
サーバー証明書の要求
  1. IE に「証明書は発行されました」ページが表示されるので、「証明書のダウンロード」をクリックし、Web サーバーの任意のフォルダに証明書を保存します。デフォルトで certnew.cer というファイル名になるはずです。
  2. 次に、サーバー証明書の Web サーバーへのインストールを行います。手順 2 と同様に、Web サーバーで IIS マネージャーを起動し、IIS セクションの「サーバー証明書」をダブルクリックします。
  3. 「操作」セクションの「証明書の要求の完了」をクリックし、「証明書の要求を完了する」ウィザードを起動します。
IIS マネージャーで証明書の要求の完了
  1. 参照 ([...]) ボタンをクリックして手順 11 でダウンロードした証明書ファイルを検索して証明書のパスを入力し、さらに「フレンドリ名」ボックスに証明書の任意のフレンドリ名を入力して「OK」ボタンをクリックします。
  2. このとき "この証明書ファイルに関連付けられた証明書の要求が見つかりません。要求を作成したコンピュータで、証明書の要求を完了する必要があります。" というエラーメッセージが表示されることがあります。その場合でも、インストールが完了していることがありますので、IIS マネージャーの画面に戻り、F5 キーを押して最新の情報を確認してください。
  3. 成功すると「サーバー証明書」セクション(IIS マネージャー画面の真ん中)に新しいサーバー証明書が追加されているはずです。
  4. 最後に SSL 接続のバインドへの追加です。IIS マネージャーで SSLを有効にするサイトを選択して「操作」セクションの「バインド」をクリックし、表示された「サイト バインド」ダイアログボックスの「追加」ボタンをクリックします。
  5. 「サイト バインドの追加」ダイアログ ボックスの、「種類」ドロップダウンリストで「https」を選択し、「SSL 証明書」ドロップダウンリストで手順 14 でインストールした証明書を選択します。
  6. 「OK」をクリックすると IIS の設定は完了です。その後、ファイアウォールの穴あけも忘れないようにしましょう。
IIS マネージャーでサイトバインドの追加

Active Directory を利用したドメイン環境であれば、クライアントの PC にも CA 証明書は自動的にインストールされるので、以上の手順までで接続時に警告を出さないで SSL 通信を行うことができます。

クライアントの PC がドメイン環境にない場合、CA 証明書は手動でダウンロードしてインストールします。その手順は次の通りです。(注:イントラネット外から CertSrv にアクセスしてダウンロードできるかどうかは未確認です)

  1. クライアントの PC から、手順 8 で述べた CertSrv サイト http://サーバー名/CerSrv/ にアクセスし、CA 証明書をダウンロードできます。Windows 認証のログインダイアログが出てくるので Administrator 権限でログインします(ドメインユーザー権限でもいいかもしれませんが未確認です)。
Administrator 権限で CertSrv にログイン
  1. 手順 8 と同じ画面が表示されるので、そこで「CA 証明書、証明書チェーン、または CRL のダウンロード」をクリックします。
  2. 「CA 証明書、証明書チェーン、または CRL のダウンロード」画面が表示されるので、「CA 証明書のダウンロード」をクリックします。うまくいけば、ダウンロードフォルダに certnew.cer という名前の CA 証明書ファイルがダウンロードされているはずです。
CA 証明書のダウンロード
  1. 手順 22 でダウンロードした CA 証明書ファイルをダブルクリックして、「信頼されたルート証明機関」にインストールします。デフォルトでは「中間証明機関」にインストールされてしまうことがありましたので注意してください。
  2. その後で、手順 18 でサーバー証明書を設定したサイトに https としてアクセスすると、以下の画像のように警告なしで接続されます。証明書も有効になっています。
クライアント PC の IE から https で接続した画面

以上、AD CS がエンタープライズ CA としてインストールされている場合の手順です。スタンドアロン CA の場合は少々面倒で、サーバー証明書を発行する前に、手動で CA 証明書を AD CS のサーバーにインストールしなければなりません。次のような手順になります。

  1. CertSrv サイトからダウンロードした CA 証明書をダブルクリックして、「信頼されたルート証明機関」にインストールする。
  2. 手順 25 でインストールした証明書を certmgr でエクスポートする。
  3. mmc + 証明書スナップインを起動する。このとき、「このスナップインで管理する証明書」を[コンピュータアカウント]に設定する。
  4. 手順 26 でエクスポートした証明書を、手順 27 で起動した mmc + 証明書スナップインで、「信頼されたルート証明機関」と「中間証明機関」にインポートする。(「信頼されたルート証明機関」だけでよいかもしれませんが未確認です)

これをしないと、サーバー証明書の発行だけでなく、証明書サービス自体もうまく動きません。"xxxx-xxxx-CAのための CA 証明書 0 のチェーンを作成できませんでした。証明書チェーンは処理されましたが、信頼プロバイダが信頼していないルート証明書で強制終了しました。 0x800b0109 (-2146762487)。" というエラーになります。

さらに、サーバー証明書を発行するとき、ダウンロードにはならず一旦保留されてしまうので、AD CS をインストールしたサーバーで、手動で mmc + 証明書スナップインを利用して証明書を発行しなければなりません。

Tags:

Windows Server

パラメータ化クエリ

by WebSurfer 2012年2月2日 22:47

パラメータ化クエリについて少々(かなり?)誤解してました。どのように誤解していたかは恥ずかしいので秘密です。(笑) 調べたことを備忘録として書いておきます。

パラメータ化クエリの説明図

パラメータ化の説明で、パラメータの入力はリテラルとして扱われるから SQL インジェクション攻撃を防ぐことができると言われています。

そこがキーポイントですが、そのリテラルというのが何だか分らないと話が始まりませんので、まずクエリの要素の名前の説明をします。以下の SELECT クエリを例に取ります。

SELECT id, Product FROM TableA WHERE Category='server'

クエリを構成する要素には、キーワード、演算子、識別子、リテラルなどがあり、上記の SELECT クエリではそれぞれ以下のようになります。

キーワード SELECT FROM WHERE
演算子 =
識別子 id Product Category TableA
リテラル 'server'

クエリをパラメータ化するというのはリテラルの部分をプレースホルダを使って記述することです。上記の SELECT クエリの例では以下のようになります。

SELECT id, Product FROM TableA WHERE Category=@Category

プレースホルダの構文はデータソースに依存します。SQL Server の場合は @parametername 形式の名前付きパラメータが使用されます。(頭に @ を付けるのは単なる命名規則です)

パラメータ名は必ずしも識別子と同じ名前にする必要はありませんが、同じにしておいた方が混乱がなさそうです。(例えば、識別子の名前が Category ならパラメータ名は @Category とする)

ADO.NET のコマンドオブジェクトは、パラメータを使用して SQL ステートメントまたはストアドプロシージャに値を渡すことを可能にしています。SQL Server の場合で、上記 SELECT クエリを例に取ると以下のようになります。

string connectionString = 
  WebConfigurationManager.
  ConnectionStrings["MyDB"].ConnectionString;

string query = 
  "SELECT id, Product FROM TableA WHERE Category=@Category";

using (SqlConnection connection =
           new SqlConnection(connectionString))
{
    SqlCommand command =
        new SqlCommand(query, connection);
    SqlParameter param = 
        new SqlParameter("@Category", SqlDbType.VarChar, 50);
    command.Parameters.Add(param);

    command.Parameters["@Category"].Value = TextBox1.Text;

    connection.Open();

    SqlDataReader reader = command.ExecuteReader();

    // 中略
}

SQL Server の場合、Parameters コレクションに追加したパラメータの名前は、クエリのパラメータ名前と一致している必要があります。(Access 等に使われる OleDb プロバイダの場合は、疑問符 (?) で指定される位置パラメータマーカーが使用されますがその話は割愛します。詳しくは、パラメータおよびパラメータのデータ型の構成 (ADO.NET) の「パラメーターのプレースホルダーの使用」セクションを参照してください)

プレースホルダの方式には静的と動的があって、SQL Server の場合は静的プレースホルダを使用します。静的/動的の違いの説明については安全なSQLの呼び出し方 - IPA 独立行政法人 情報処理推進機構を参照してください。

動作は次のとおりです(上の図も参照ください)。まず、プレースホルダのままのクエリをデータベースエンジン側にあらかじめ送信して、実行前にクエリのコンパイルなどの準備をしておきます。クエリの実行の段階で、Parameters コレクションに追加したパラメータの値をデータベースに送信し、データベースがバインド処理します。

ユーザー入力から直接クエリを組み立ててコマンドテキストとして渡すのとは異なり、パラメータの入力は実行可能なコードとしてではなく、リテラル値として扱われます。これにより、攻撃者がサーバーのセキュリティを侵害するコマンドを "注入" しても、注入した値はリテラルの外にはみ出すことはない(上の SELECT クエリの例で言うと、WHERE 句の条件が true または false になるだけ)ので、SQL インジェクション攻撃を防ぐことができます。

なお、パラメータ化するとエスケープ処理されるという話を時々聞きますが、少なくとも SQL Server の場合はそれは誤解です(エスケープ処置はされません。静的プレースホルダ方式なので処置する必要がありません)。

パラメータ化のもう一つのメリットにパフォーマンスの向上があります。それについては 第 4 回 アドホック クエリのパラメータ化 が参考になると思います。このページには、SqlParameter クラスを利用した場合、SQL Server の内部的にどのようにパラメータ化クエリが実行されるかも書いてあって(sp_executesql に変換されて実行される)、興味深いと思いました。

-------- 2016/6/5 追記 --------

上に述べたように、SQL インジェクションの防止とパフォーマンスの向上がパラメータ化クエリを使う主な目的ですが、それ以外にも照合順序の違いによって文字化けに悩むことがなくなるという副次的な効用もあります。

詳しくは別の記事「パラメータ化の副次的な効用」に書きましたので、興味がありましたら見てください。

Tags:

ADO.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar