XSS対策に入力時エスケープは非常にややこしい

to-RさんのXSSの脆弱性を限りなくなくす方法を読んでなんかもにょもにょしたのでエントリーを書く。多分、to-Rさんはこれから書くことに関して理解してて、あの対策を行なってるのかもしれないけど、それでも書く。自分の勉強も兼てるので変なところがあれば教えていただけるとありがたいです。

入力時エスケープは非常にややこしい

確かに、入力値に必ずエスケープしておけば、XSS対策漏れにはなるかもしれない。けれど非常にややこしいことになる。

例えば、受け取ったデータの文字列に対して文字数制限のバリデーションを行なうときにわざわざアンエスケープの処理を行なわないといけないし、DBへの保存の際にもアンエスケープが必要になる。ブログとかでフォームから受け取ったデータのうち、一部のタグは許容するときとかもかな。

ベストの対策はアプリの性質に合わせたエスケープなんだけども、これって完全になくすにはかなりの几帳面さが必要になるんじゃないかなと思います。(規模が大きくなればなるほど)

とエントリーでは書かれているけど、この対策が大規模になればなるほどXSSに限らず色々な問題が発生する気がする。大規模であればあるほど、出力箇所をみて「対策されている」というのがわかるのが大事。

コードを書きながら「DBに保存するからアンエスケープ・・・」「スクリプトとして出力するからアンエスケープ」って考えるよりは、「HTMLの出力時にエスケープ」の方がわかりやすいはず。出力時をみればいいんだから。

ちなみにフレームワークやテンプレートエンジンが出力時のエスケープをデフォルトで行なうってのは賛成です。なぜなら使っているフレームワークまたはテンプレートエンジンがエスケープしているということが自明なら、エスケープの有無を確認する必要がなくなるから。PHPとかWeb特化とか言うぐらいなら、デフォルトでエスケープして出力すればいいのにと思う。

なんかXSS対策とかエスケープって言い方がよくない気もするな。普通に「スクリプトを無効にする」とかで良い気がしてきた。スクリプトが有効になるのは、HTML出力時なんだからその時に無効化すればいいよね。

というか、PHPの人はmagick quoteでこりたと思ってたんだけど。

追記

ブクマコメ、高木さんより。
「普通に「スクリプトを無効にする」とかで良い気がしてきた」< XSSはスクリプトだけじゃない。>iframe<の挿入<form>の挿入を考えてみるよろし。CERT CA-2000-02ではXSSと呼ばず「Malicious HTML Tags Embedded in Client Web Requests」と呼んだ

あー、確かにそうですね。指摘ありがとうございます。Malicious HTML Tags Embedded in Client Web Requestsは初耳でした。