質問: **質問** HTMLエスケープはどういう時に必要ですか? --- **質問経緯** ・これまで、出力直前に必ずHTMLエスケープを実施してきました。ここでいうHTMLエスケープとは、PHPの htmlspecialchars のような、htmlタグを無効化するものを想定しています ・しかし、(HTMLエスケープ処理を)必ずしも毎回実行しなくてもよいのでは? と思ったので質問します --- **下記ケースでは、それぞれ(出力直前に)HTMLエスケープが必要ですか?** * a.「任意user」がフォームからPOST送信した内容を、受信後すぐにブラウザ出力 * b.「自分」がフォームからPOST送信した内容を、受信後すぐにブラウザ出力 * c.DBから取得した内容をブラウザ出力。※DBデータは「任意user」がフォームからPOST送信した内容 * d.DBから取得した内容をブラウザ出力。※DBデータは「自分」がフォームからPOST送信した内容 * e.DBから取得した内容をブラウザ出力。※DBデータはフォームを使用せずINSERTした内容
回答: 基本的には外部から入力されるデータは「ユーザの誰が」入力したかは関係なく、許可していない限りは出力する際にエスケープするべきです。 エスケープしている処理を入れているということはクロスサイトスクリプティングの脆弱性については理解しているという前提で記述します。もし、そのあたりが不明な場合はIPAの安全なウェブサイトの作り方 を参考にしてください。 > > a.「任意のuser」がフォームからPOST送信した内容を受信後ブラウザに出力 > > b.「自分」がフォームからPOST送信した内容を、受信後すぐにブラウザ出力 > > > これらは任意のユーザであれば危険で自分であれば安全かと認識される人もいますが、これは間違いです。 例えば、ログインしている人のメールアドレスを表示するページがあった時に、そのページにXSSがあったとします。 攻撃者がそのページにXSSで相手のメールアドレスを抜き取るスクリプトを仕込み、さらにそのURLをターゲットににアクセスさせるようにリンクを作ってアクセスさせたらどうなるでしょうか? 自分がアクセスしているとしてもそれを横から抜かれるのがXSSの特徴です。 > > c.DBから取得した内容をブラウザ出力。※DBデータは「任意user」がフォームからPOST送信した内容 > > d.DBから取得した内容をブラウザ出力。※DBデータは「自分」がフォームからPOST送信した内容 > > > これらも「ユーザの誰が」は関係なくクロスサイトリクエストフォージェリー(CSRF)の脆弱性と合わせて、XSSで攻撃される可能性があります。 CSRFはPOSTを偽装することで有効なリクエストとみなす攻撃なので、 例えば住所を変更するようなページにSCRFがあったとします。とすると攻撃者がまたも適当なページで住所を変更するPOSTを投げるように仕向けます。 そのPOSTデータを、誤って処理してしまって別のページでXSSで表示したら情報が抜かれたということが起きますね。 > > e.DBから取得した内容をブラウザ出力。※DBデータはフォームを使用せずINSERTした内容 > > > ここまでで「ユーザの誰かが」と言っていましたが、この質問に関しては「システム」が出力したデータに関しての質問なので安全性が確保できているのであれば、エスケープの必要はないでしょう。 また、「許可していない限り」とあるようにユーザにHTMLを入力してもらって、出力するようなことはシステムの仕様であり得ると思います。その場合は危険なタグを除去するなどの処理が必要になりますが、往々にして非常に難しい仕様になるのでほとんどの場合はマークアップ言語を用いて運用することが多いと思います。 あくまで脆弱性とはその言葉の通り脆く弱いところでそれだけでは実はすぐには攻撃が通ったりセキュリティ事故は起こらないものもあります。ですが、放置しておくとそれらが組み合わさって大事故が起こりえます。 ぜひ日ごろから注意して、ウェブサイトを作ってみてください。