Text::Xslateで安全なテンプレート生活を送ろう!
いよいよクリスマスまで残り4日となりましたが皆様はいかがお過ごしでしょうか。クリスマスが終わると年越しですね。年末年始は枕を高くして眠りたいですね。XSSの恐怖に怯えたくないですね。テンプレートファイルのgrepログを眺めるだけの単純なお仕事で時間を使いたくありませんね。それならText::Xslateを使ってエスケープのことは忘れましょう!
Text::Xslateはウェブアプリケーションのために最適化したテンプレートエンジンです。Xslateの一部は今年のJPerl Advent Calendar Casual Trackでも紹介されていますね*1。
- [/articles/advent-calendar/2010/casual/8:title=Kolonでかこう]
さて、ウェブアプリケーションではユーザーからの入力をHTMLページに埋め込むことがよくありますが、そこで気をつけなければならないのがXSSですね。このあたりのことは私よりも詳しい方がおおぜいいらっしゃるのでそちらを参考にしてください。
- Text::MicroTemplate - テンプレートエンジンのセキュリティと利便性
- XSSに強いウェブサイトを作る – テンプレートエンジンの選定基準とスニペットの生成手法
- HTMLのscriptタグ内に出力されるJavaScriptのエスケープ処理に起因するXSSがとても多い件について
- XSSを回避しつつ、テンプレートからJavaScriptにJSONで値を渡す方法
Xslateは、特に上記リストの最初のエントリで紹介されているText::MicroTemplateのアイデアを採用し、テンプレートに埋め込む値をデフォルトでHTMLエスケープするようにしています。Template::ToolkitやHTML::Templateと異なり、原則としてテンプレート側にエスケープ処理のためのコードを書く必要がありません。というより、書いてはいけません。このAdvent Calendar用のテンプレートを見ていただくとそれがわかると思います。
- https://github.com/perl-users-jp/perl-advent-calendar/blob/master/tmpl/index.html
- https://github.com/perl-users-jp/perl-advent-calendar/blob/master/tmpl/entry.html
entry.htmlではText::Xatenaで整形したHTMLを埋め込みますが、その部分のテンプレートは以下のようになっています。
<div class="entry-content"> [% text %] </div>
このtextはエスケープされませんが、それはアプリケーション側でそのまま(raw)埋め込むよう指定しているからです。
#line 295 text => mark_raw($text),
テンプレート側でもmark_rawを行うことはできますが、これを使うのは開発中だけにしておき、リリースの際は全てアプリケーション側で処理するようにしたほうがいいでしょう。重要な処理をアプリケーションコードに分離することでメンテナンスしやすくなりますし、またアプリケーションとテンプレートをうっかり同期し忘れてXSSが発生するというアクシデントが原理的に起こらなくなります。
安全なテンプレートエンジンを使って年末年始はのんびりしましょう!
以上、gfxでした!