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

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

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

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

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

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


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

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

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

入力値検証の目的は「ユーザビリティ」と「システムの信頼性」の向上

ゆうべ寝床で思いついた意見。さっそくブログに書こうと、誰か他に言っている人がいないか調べたら、徳丸本の76ページに思いっきり書いてあった。

すなわち、入力値検証の目的は以下の通りです。

  • 入力値の間違いを早期に発見して再入力を促すことにより、ユーザビリティ(使いやすさ)を向上する
  • 間違った処理を継続することによるデータの不整合などを防ぎ、システムの信頼性を向上させる

もう、これでFAじゃないですか。精読してない俺の馬鹿。

たとえば、ユーザ登録フォームでパスワードが未入力だった場合、アプリケーションは「登録処理に失敗しました」などという曖昧なものではなく「パスワードは必須です」のような明確なメッセージを返すべきだ。それがユーザビリティの向上。

DBにおかしな値が登録されないようにすべきなのは言わずもがな。Railsのドキュメントに「Validations are used to ensure that only valid data is saved into your database.」とある通り。これが信頼性の向上。


ちなみに、このドキュメントには、以下のようにも書かれている。

  • Model-level validations are the best way to ensure that only valid data is saved into your database.
  • Controller-level validations can be tempting to use, but often become unwieldy and difficult to test and maintain. Whenever possible, it's a good idea to keep your controllers skinny, as it will make your application a pleasure to work with in the long run.
  • It's the opinion of the Rails team that model-level validations are the most appropriate in most circumstances.

なので、Railsがコントローラでのバリデーションを推奨するようになったというのはデマです。


入力値のなかには、DBと無関係なものもありうる。「HTML文書のURLを入力するとtitle要素の文字列が返るAPI」を想像すると分かりやすいだろうか。入力値がURL形式であれば、そのURLにアクセスし、ドキュメントをパースするだけ。

こうした、DBと無関係な入力値は、コントローラでバリデーションしてもよいように思える。ただ、少なくともRailsの流儀では、ActiveModel::Modelをインクルードしたモデルでバリデーションするのが普通っぽい。まあ、いずれにしても趣味の問題だろう。


徳丸本の72ページに「文字エンコーディングの妥当性検証を行う理由は、文字コードを使った攻撃手法があるからです」とあるが、ここはしっくりこない。「入力値検証の一部」あるいは「入力値検証の前提」(文字エンコーディングの妥当性を検証しないと、入力値を正しく検証できない)という説明ではダメなんだろうか。

各種インジェクション攻撃やらディレクトリ・トラバーサル攻撃やらについては、それらが起きそうな場所で、文字エンコーディングの妥当性検証を行えばよいわけだし、それほど大変なイメージがいまだに持てないんですよね。しつこくてすみません。

記事検索
Twitter