データバインド時のHTMLエンコード
厳密に型指定されたデータコントロール機能で、データバインドがますます便利になりました。しかしデータバインドを行う際には、XSS(クロスサイトスクリプティング)の脆弱性にも気を付けなければいけません。特に注意が必要となるのが、Labelコントロールを使う場合です。
XSS未対策の場合
まず、XSS対策をしていないデータバインド式の書き方をリスト3に示します。コードは会議室検索画面(MeetingRooms.aspx)のGridViewコントロール内で、会議室の場所名を表示している箇所です。
<asp:GridView ID="MeetingRoomsGridView" runat="server" AutoGenerateColumns="False" DataSourceID="MeetingRoomsObjectDataSource" DataKeyNames="MeetingRoomId" ItemType="MRRS.Entity.MeetingRoom" OnSelectedIndexChanged="MeetingRoomsGridView_SelectedIndexChanged"> <Columns> <asp:CommandField ShowSelectButton="True" /> <asp:BoundField DataField="MeetingRoomName" HeaderText="名称" SortExpression="MeetingRoomName" /> <asp:TemplateField HeaderText="場所" SortExpression="LocationId"> <ItemTemplate> <asp:Label ID="LocationNameLabel" runat="server" Text="<%# Item.Location.LocationName %>" /> </ItemTemplate> </asp:TemplateField> </Columns> <EmptyDataTemplate> 検索条件に該当するデータがありません。 </EmptyDataTemplate> </asp:GridView>
この状態で、例えば表1のようなスクリプトが埋め込まれた場所データが、場所マスターに登録されていたらどうなるでしょうか?
Id | 場所名 |
---|---|
1 | <script>alert('test');</script> |
そこで実行してみた結果、次の図5のように、スクリプトが実行されてしまいます。つまり、XSSの脆弱性があるということです。
![図5:スクリプトが実行された結果](http://cz-cdn.shoeisha.jp/static/images/article/7235/7235_05.gif)
XSSへの対策
XSSへの対策を行うには、HTMLエンコードを行わなければなりません。ASP.NET 4.0までは、HttpUtilityクラスのHtmlEncodeメソッドを使い、次のリスト4のように書く必要がありました。
<asp:Label ID="LocationNameLabel" runat="server" Text="<%# HttpUtility.HtmlEncode(Item.Location.LocationName) %>" />
ただ、この方法では記述が長くなってしまうので、少し面倒です。そこで、ASP.NET 4.5では、自動的にHTMLエンコードを行うデータバインド式が導入されました。自動でHTMLエンコードを行わせたい場合、リスト5のようにデータバインド式を「<%#: %>」のような":"がついた形式で書きます。
<asp:Label ID="LocationNameLabel" runat="server" Text="<%#: Item.Location.LocationName %>" />
このように記述を変更してから実行すると、今度はスクリプトが実行されずにそのままデータが表示されることが確認できます(図6)。
なお、リスト2のテキストボックスにバインドしている箇所では、HTMLエンコードを行うように指定していません。これはテキストボックスのTextプロパティでは、自動でHTMLエンコードが行われるという仕様があるためです。
テキストボックスが表示されるとき、このプロパティの内容はHTMLエンコードされます。例えば、このプロパティを"<b>Test</b>"に設定した場合、太字の"Test"ではなく"<b>Test</b>"がブラウザに表示されます。
データバインドではなく、ASP.NET Webフォームへの埋め込み式でもHTMLエンコードを行いたい場合があると思います。
そんなときはリスト6のように、ASP.NET 4.0で追加されたHTMLエンコード式を使いましょう。
<!-- 通常の埋め込み式 --> <%= "<s>non encoded</s>" %> <!-- HTMLエンコード式 --> <%: "<s>html encoded</s>" %>
実行した結果が図7です。HTMLエンコード式の方を見ると、きちんとHTMLエンコードされているのが確認できます。
![図7:HTMLエンコード式の実行結果](http://cz-cdn.shoeisha.jp/static/images/article/7235/7235_07.gif)
まとめ
今回はASP.NET 4.5の新機能のうち、目玉の一つである「厳密に型指定されたデータコントロール」、そしてHTMLエンコードを行うデータバインド式について解説しました。今回のポイントは次のとおりです。
-
「厳密に型指定されたデータコントロール」を用いると、データバインド式の内部を型安全に記述できる
- データコントロールのItemTypeプロパティに、バインドするオブジェクトの型名を明示する
-
データバインド式の中では、Item、BindItem変数を使う
- Item : 一方向、出力のみ
- BindItem : 双方向、入出力
- データバインド式の中でIntelliSenseによるコード補完も利くようになる
-
LabelコントロールのTextプロパティへのデータバインドは、XSS対策のためHTMLエンコードが必要
- 従来はHttpUtility.HtmlEncodeメソッドを使っていた
- 新たに追加された「<%#: %>」形式のデータバインド式を用いることで、自動的にHTMLエンコードが行われる
- TextBoxコントロールのTextプロパティは自動的にHTMLエンコードが行われる仕様になっている
さて次回は、もう一つの目玉機能である「モデルバインド」について、深く掘り下げてみようと思います。お楽しみに。