Dec 28, 2005

サニタイズ言うなキャンペーンについて

隣のオフィスの人がこんなことを書いていました:

高木浩光@自宅の日記 - プログラミング解説書籍の脆弱性をどうするか, 「サニタイズ言うなキャンペーン」とは何か, ASPとかJSPとかPHPとかERBとか、逆だ..

なるほどね、「サニタイズ言うなキャンペーン」とはそういう意味でしたか。私自身、PHPやPerlで適当に書き散らしたものをこのブログで公開してしまっているわけでそれらについてすべてケアできているとは到底思えない、これから気をつけようと思いました(笑)。

で、やっぱり思ったのは、PHPにしろPerlにしろSQLにしろ、String Processingの範疇にあるプログラムは、ほとんど常に処理中の文字列が指し示す「型」を意識しなければ作れないにも関わらず、最もベーシックな型である「文字列型」だけを使って実装されていることに、一番の問題があるのではないか、ということです。

それゆえ、型を意識せずにプロトタイピングした後で正常に動作するように「サニタイズコード」を挿入するという流儀が一般的になっていて、その「手順のシンプルさ」や「(結果として得られる偶発的な)コードのミニマムさ」が、滑稽にも(!)一種の美意識のように思えてしまうのでしょう。

型の話に戻ると、例えばフォームから入力された文字列とそれを「エスケープした」文字列とは異なる型を持っていると考えることができます。その指し示す「内容」は同じだとしてもそのまま比較したり、結合したりすることは、できないか意味がないと考えるのが自然です。それを「型」だと認識していないプログラマであっても仮想的にはその事実を意識してプログラムを書かざるを得ません。

また、HTMLの出力やSQLでの問い合わせの際に何らかが変換が必要になるのは、それらの生成に先立ってプログラムが保持していた値の型と、HTMLの持つべき型・SQL文の持つべき型が異なるため(あるいは問い合わせ結果に含まれる文字列の型とプログラムで保持すべき値の型が異なるため)です。

高木さんの主張は、こうした「暗黙的には存在する」型システムを開発者が強く意識すべきだという主張にほぼ等価に思えます。サニタイズという言葉は単なる文字列から文字列への変換操作だけを連想させ、型に対するプログラマの認識を不確かなものにしてしまいます。例えば、

'名前:'.htmlspecialchars($row['name'], ENT_QUOTES)

は、何かの文字列と「サニタイズされた」文字列を結合したものを返しますが、それはちゃんとサニタイズされた文字列になるのでしょうか。今我々はたまたま固定の安全な文字列「名前:」と結合したことを知っているから、これが安全であることを認識するに過ぎません。そしてそれがたまたまHTMLとして安全に出力するに足る性質を持っているというだけです。それに引き換え、htmlspecialcharsを一種の型変換子と考えれば、

htmlspecialchars('名前:'.$row['name'], ENT_QUOTES)

は、二つの文字列を結合し、それを安全な型に変換したものを返すことになります。したがって安全であると自明に分かります。重要なのは方法が貧乏か富豪かということではなく、確認できるべきことが容易に確認できるかどうかです。

さら言うと、本来なら左辺値の型に自動的に変換してくれるような気の利いたプログラミングシステムがあればなお間違いを減らすことができますが、それは多くの処理系で望めません。苦肉の策というわけではないですが、高木さんはhtmlout_tagとかhtmlout_quoteとかいう関数を用意して安全な文字列への変換と出力を行うこと薦めています。これがベストという訳ではなく、安易に思いつくAlternativeとしては、CGI.pmのオブジェクト指向スタイルのように、出力用の文字列を生成するコンストラクタを用意してやるのも悪くない方法でしょう(CGI.pmが必要な変換を行うかどうかは別にして)。

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com