2013年08月

HTMLエスケープのみで済むコンテキストにおいてだけ、動的出力を許すのはどうか

前回の日記で、コンテキストに応じたオートエスケープ機能をもつテンプレートエンジンに期待する旨を書いた。そうしたテンプレートエンジンは、すでにいくつも存在するが、メジャーにはなっていないようだ。少なくとも、Rubyではめぼしいものがなかった。

考えてみると、さまざまなコンテキストで動的に文字列を出力しようというのが無茶なのかもしれない。発想を変えて、HTMLエスケープのみで済むコンテキストにおいてだけ、動的出力を許すことにしてはどうか。

その前提からは、以下のコーディング規約が導き出せる。

  • クライアントサイドのロジックは、関数呼び出しや値の代入部分も含め、すべて静的に書く
  • クライアントサイドのロジックに渡したい値は、任意のHTML要素の属性値として出力する

URLの出力については、テンプレートエンジンのヘルパーメソッド経由でのみ許可するのが無難だろう。パーセントエンコーディング漏れがなくなるし、スキームのチェックもできる。

「結局、規約かよ」と思われるかもしれないが、「SQL文の実行にはプリペアド・ステートメントを使うべし」という話だって、つまりは規約の話なのだ。DOM Based XSS「対策」だって、エスケープ漏れを防ぐには、何らかの規約を設けるのが現実的だろう。

こう考えてくると、コンテキストに応じたオートエスケープ機能をもつテンプレートエンジンの必要性は薄くなる。メジャーになっていないのは、これが理由かもしれない。

目的はセキュリティ対策ではない/オートエスケープへの期待

入力バリデーションはセキュリティ対策です。システムが意図通りに動作するように対策する入力バリデーションをセキュリティ対策ではないとするならば,システムが意図通りに動作するようエスケープしたりヘルパー関数(Viewヘルパーやプリペアードクエリ)を利用することもセキュリティ対策ではないということになってしまいます。

第45回 入力バリデーションはセキュリティ対策 :なぜPHPアプリにセキュリティホールが多いのか?|gihyo.jp … 技術評論社

「セキュリティ対策ではないということになってしま」ってもよいのではないか。

われわれWebアプリ開発者は、SQLインジェクションを防ぐためにプリペアド・ステートメントを使うのではない。SQLを正しく組み立て、意図通りに実行させるために、簡単で確実なプリペアド・ステートメントを利用するのだ。その結果、SQLインジェクションは防げるだろうが、それは主眼ではない。

XSSとエスケープについても同様である。XSSを防ぐためにエスケープするのではない。HTMLを正しく組み立てるために、適切なエスケープ処理を施さなければならないのだ。


とはいえ、この「適切なエスケープ処理」が難しい。SQLにおけるプリペアド・ステートメントのような、簡単で確実な手段はないものか。

Closure Templatesのオートエスケープが最強すぎる件 - teppeis blog」で紹介されている Closure Templates は、コンテキストに応じた適切なエスケープ処理を自動的に施してくれるものらしい。

こうした方向にテンプレートエンジンが進化していけば、Webアプリ開発者の負担が減りそうだ。

記事検索
Twitter