連載:〜ScottGu氏のブログより〜

ASP.NET 4(そして、ASP.NET MVC 2)におけるHTMLエンコーディング出力用の新しい<%: %>構文

Scott Guthrie 著/Chica
2010/04/12

 本記事は、Microsoftの本社副社長であり、ASP.NETやSilverlightなどの開発チームを率いるScott Guthrie氏のブログを翻訳したものです。氏の許可を得て転載しています。

[ブログに加え、現在Twitterを使って簡単な更新やリンク共有を行っています。twitter.com/scottguで、私をフォローしてください。]

 これは、VS 2010および.NET 4リリースに向けたブログ投稿シリーズの第19弾です。

 本日の投稿では、小さいけれど非常に便利な、ASP.NET 4で導入された新しい構文機能をカバーします。これは、自動的にHTMLエンコードをコード・ナゲット(code nuggets)内に出力する機能です。これはクロスサイト・スクリプト・インジェクション(XSS)やHTMLインジェクション攻撃からアプリケーションやサイトを防御する手助けとなり、それを簡潔な構文を使用して行えます。

HTMLエンコーディング

 クロスサイト・スクリプト・インジェクションとHTMLエンコーディング攻撃の2つは、Webサイトやアプリケーションにとって悩みの種となる、最もよくあるセキュリティ問題です。これらは、ハッカーがWebページにクライアント側のスクリプトやHTMLタグを挿入する方法を見つけることによって発生し、そして、そのページがサイトへの訪問者によって見られることになります。これはサイトを破壊したり、ハッカーがクライアント・スクリプトのコードを走らせたりするために利用されます。これによりハッカーは、クッキーのデータを盗んだり、ユーザー情報を取得したりでき、悪事を働くことができます。

 クロスサイト・スクリプティング攻撃を緩和する1つの方法は、描画される出力を確実にページ内でHTMLエンコードしておくことです。これにより、エンドユーザーによって入力/修正される可能性のあるすべてのコンテンツは、<script>や<img>要素のようなタグを含んだページとして再出力できません。

■今日のコンテンツのHTMLエンコード方法

 ASP.NETアプリケーション(特にASP.NET MVCを使用したもの)は、しばしば出力を描画するのに、<%= %>のコード・ナゲット式の使用に頼っています。開発者は今日では、出力が描画される前にHTMLエンコードするために、これらの式の中でServer.HtmlEncode()やHttpUtility.Encode()のヘルパー・メソッドをよく使用します。これは以下のようなコードを使用して行えます。


図1

 これはうまく動作しますが、2つのマイナス点があります。

  1. 少し冗長である
  2. 開発者はServer.HtmlEncodeメソッドの呼び出しをよく忘れるのと、アプリケーション全体でその使用を確認する簡単な方法がない

新しい<%: %>コード・ナゲット構文

 ASP.NET 4では、新しいコード式の構文(<%: %>)を導入しました。これは<%= %>ブロックが行うような出力を描画するのですが、その前に自動的にHTMLエンコードも行います。これは上記の例で行ったような、明示的にコンテンツをHTMLエンコードする必要性を排除します。その代わりに、以下のようなより簡潔なコードを書くだけで、まったく同じことを実現できます。


図2

 <%: %>構文を選択すれば、既存の<%= %>コード・ブロックのインスタンスを簡単に置換できます。また、確実に正確な動作をするように、アプリケーション内でHTMLエンコーディングが行われていないケースを探して検証するために、<%= %>要素を簡単にコード・ベースで検索できます。

二重エンコーディングの回避

 通常、コンテンツをHTMLエンコーディングすることが最善策なのですが、出力するコンテンツがHTMLであるときや、すでにエンコードされているような場合、それを再びHTMLエンコードしたくはありません。

 ASP.NET 4では、新しいIHtmlStringインターフェイスを(HtmlStringクラスという具体的な実装とともに)導入しており、HTMLとして表示するために、すでにその値が適切にエンコードされた(もしくは検証された)ことを示すように型を実装でき、これにより、その値は再度HTMLエンコードされなくなります。<%: %>コード・ナゲット構文はIHtmlStringインターフェイスの存在をチェックし、もしその値がこのインターフェイスを実装していれば、そのコード式の出力をHTMLエンコードしません。これにより開発者は<%= %>または<%: %>コード・ナゲットのどちらを使用するかを、ケースごとに決定しなくてよくなります。その代わり、<%: %>コード・ナゲットを常に使用して、すでにHTMLエンコードされたプロパティやデータ型にはIHtmlStringインターフェイスを実装します。

■<%: %>と併せてASP.NET MVC HTMLヘルパー・メソッドを使用

 このHTMLエンコーディング・エスケープ・メカニズムが便利な実例としては、ASP.NET MVCとHTMLヘルパー・メソッドを使用するシナリオを考えてみてください。これらのヘルパー・メソッドは通常、HTMLを返します。例えば、Html.TextBoxヘルパー・メソッドは、<input type="text"/>のようなタグを返します。ASP.NET MVC 2では、これらのヘルパー・メソッドはデフォルトでHtmlString型を返します。これは、その返された文字列のコンテンツを安全に描画でき、<%: %>ナゲットによってエンコードされるべきでないことを示しています。

 これにより、それらのメソッドを<%= %>のコード・ナゲットのブロック内で使用できます。


図3

 またのコード・ナゲットのブロック内でも同じです。


図4

 上記の両方のケースでは、ヘルパー・メソッドから返されたHTMLのコンテンツはHTMLとしてクライアントに描画され、<%: %>コード・ナゲットは、二重エンコーディングを回避します。

 これにより、アプリケーションで<%= %>のコード・ブロックの代わりに、<%: %>コード・ナゲットを常にデフォルトとして使用できます。もしどうしても必要なら、<%= %>が使われている個所を探し出して、どんなケースでもエラーとしてフラグを立て、常にHTMLエンコーディングが行われるように強制するような構築ルールを作成することも可能です。

ASP.NET MVC 2ビューのスキャフォールディング

 VS 2010(もしくは無償のVisual Web Developer 2010 Express)を使用してASP.NET MVC 2アプリケーションを構築すると、“Add View”ダイアログを使用してスキャフォールドされたビューは、現在デフォルトで<%: %>ブロックを常に使用し、すべてのコンテンツを出力するようになっていることがお分かりいただけると思います。例えば以下では、Articleオブジェクトに対して単純な“Edit”ビューをスキャフォールドしています。ラベル、テキストボックス、検証メッセージに対する<%: %>コード・ナゲットの3つの使用方法をご確認ください(HTMLヘルパー・メソッドですべて出力されています)。


図5

まとめ

 新しい<%: %>構文は自動的にコンテンツをHTMLエンコードし、それを出力として描画する簡潔な方法を提供します。これにより、コードを少し簡略化でき、サイト上のすべてのコンテンツが常にHTMLエンコーディングされているかどうかを簡単にチェック/検証できるようになります。これはアプリケーションをクロスサイト・スクリプト・インジェクション(XSS)やHTMLインジェクション攻撃から防御するのに役立ちます。

 Hope this helps,

 ScottEnd of Article

   
 
インデックス・ページヘ  「〜ScottGu氏のブログより〜」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間