XSS や CSRF の話題は相変わらず結構多いですね。例えば、はまちや2さんのブログに最近書かれたエントリとか。
CSRFで強制ログインさせるというアイデア - ぼくはまちちゃん!(Hatena)
曰く、Hatena や Facebook など多くのサービスがログイン画面では CSRF 対策されていないとか。実際に書かれているようなことが起きたら怖いですねー。
で、本題なんですが、ASP.NET を使ったサービスでは XSS や CSRF に関してはあまり被害を聞かないなーと思いました。ぶっちゃけ、採用サイトが少なすぎるのが理由な気もするんですが、SQL インジェクションはよく聞きますが、XSS・CSRF は自分は特に被害を知りません。
XSS
XSS は悪意のある入力内容が、適切にエスケープされずに出力された場合に発生します。ということでエスケープをしましょう。
そもそも ASP.NET には HTML タグっぽいものが送信された時には「危険なタグが〜」というエラーになるので、XSS には比較的耐性があるかと思います。
Web Forms
<%-- ASP.NET 4 以前 --%> <%= HttpUtility.HtmlEncode(Model.Name) %> <%-- ASP.NET 4 以降 --%> <%: Model.Name %>
Web Forms では ASP.NET 4 から <%: %> コードナゲットが追加され、デフォルトでエスケープされるようになりました。ASP.NET 4 より前では手動でエスケープする必要があります。
MVC
@* Razor を使用 *@ @Model.Name @* エスケープされたくない場合 *@ @Html.Raw(Model.Name)
Razor はデフォルトでエスケープされるので、何も考えずにそのまま書けます。エスケープされたくない場合は Html.Raw ヘルパーを使います。
Web Pages
@* Razor を使用 *@ @Model.Name
Web Pages も Razor なので MVC とまったく同じです。
CSRF
不正なフォームから POST された時には処理を行ってはダメですよ。ワンタイムトークンを発行して、正規のリクエストか判別する方法が一般的かと。
Web Forms
protected override OnInit(EventArgs e) { base.OnInit(e); ViewStateUserKey = Session.SessionID; }
ASP.NET の組み込み機能を活用し、Web 攻撃を回避する
Web Forms ではビューステートを持ってるので、そこにユニークな値をセットすることで対策を行えます。MS 的にはセッション ID を勧めているようです。
MVC
@using (Html.BeginForm()) { @* トークンを埋め込む *@ @Html.AntiForgeryToken() }
// トークンを検証する [ValidateAntiForgeryToken] public ActionResult Create() { return View(); }
HTML 側で Html.AntiForgeryToken ヘルパーを呼び出すとクッキーと hidden 値にトークンが書き込まれます。そして POST 先のアクションに ValidateAntiForgeryToken 属性を付けておくと、自動的にトークンの検証が行われます。
MVC ではこれだけで CSRF 対策が出来るので、実装しておくことをお勧めします。
Web Pages
<form action="" method="post"> @* トークンを埋め込む *@ @AntiForgery.GetHtml() </form>
if (IsPost) { // トークンを検証 AntiForgery.Validate(); }
AntiForgery ヘルパーが用意されているので、MVC までとはいきませんが、かなり簡単に対策出来ます。仕組みは MVC と同じというか MVC は AntiForgery ヘルパーを使って属性を実装しています。
ちなみにトークンの検証に失敗したときには例外が投げられます。
SQL インジェクション
LINQ to SQL や Entity Framework で LINQ を使いましょう。以上!!