gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

サニタイズとかそーゆー話

んっと。最近騒がれているサニタイズ周りのお話なのですが。
実は私は「データは汚染されっぱなし」派です。…って書くと海よりも山よりも大きな誤解を生みそうですが :-P


一般にサニタイズって言っても、実際には「対DB向け」と「対HTML出力向け」では異なったサニタイズが必要になります。
なので、個人的には「入り口で統一的にサニタイズする」ってことをあんまりやらないですし、ましてや途中でなんとなくなんてぇ恐ろしいことは間違っても。
結局のところ「使うときにやむを得ずするもの」だと思っているので、私は「データは常に汚染されている」ことを前提に、出力(画面だろうがファイルだろうがDBだろうが)タイミングで「出力方式にそぐうサニタイズ」をするようにしています。
そう考えると、一部言われている「サニタイズのための置換を二重三重にやってしまって以下略」という話は十分にフォロー&ガードできてしまいます。


んで。そんな話をしているのは、Jittaさん経由( http://blogs.wankuma.com/jitta/ )、GIJOE氏の…Blogじゃないなぁ。記事、と言ったほうがいいのだろうか? から、なのですが。( http://www.peak.ne.jp/xoops/md/news/article.php?storyid=81 )
ちっと興味を持って拝見するに…正直なところ、個人的には「甘い」としか思えないです。
具体的に、私が個人的に甘さを感じるラインを書いてみたいかと。


まず「idとdateはサニタイズする?」論争。
ここで出てくるのは有名な(有名だと思うんだけどなぁ…どうなんだろ?)高木先生。Blogは必見。今回は http://takagi-hiromitsu.jp/diary/20051227.html を取り合えずご覧くださいませませ。
まずGIJOE氏は概ね「なぜ $row['id'] を、htmlspecialchars() に通さなくて良いのか。それを考えていただくことが主目的となる局面で」、「htmlspecialchars()を通す必要がある型とそうでない型がある、ということです。」等。つまりは「データの形によってサニタイズが必要である場合とそうでない場合があるのに画一的にサニタイズするのは如何なものか」的見地であることが伺えます。
一方で高木先生は「プログラムの全体を精査すれば、「$row['id']」の値が数値しかとらないことを確認できるだろうし、「$row['postdate']」の値が日付を表す文字列しかとらず、HTTPリクエストの値(CGI入力)に依存していない式だとということも確認できるのだろう。だが、そのような確認作業をしないと正しいコードかどうかわからないような、プログラムの書き方をすべきでない。セキュリティ云々以前に、プログラムの開発方法論として、できるだけ局所的な視点でコードの正当性を確認できるように書くのが、近代プログラミングの基本だ。つまり、このコード断片だけ見て、問題がないとわかるように書くべきである」という風な主張をなさってます。
個人的には私は高木先生の意見を支持します。
そもそもデータ型なんてのは「ふわふわしている」もんです。というか、GIJOE氏は「$row[]だからDBの結果セットであるのは明らかですし、'id'は整数型、'*date'は何らかの時間型だと、十分に局所的に判断できます。」とか書いてますが、idが整数型でdateがが時間型である保障なんてどこにもないです。っていうかそのまえに、idって必ず整数型なんですか? 状況にも拠りますが、私は必要に応じて文字型を取る場合がありえますが。
大体、いろいろなところからの「ご無体な仕様変更」についてはどのようにお考えなのでしょうか?
んで、そんな「多分こうだよねぇ」的見地に立って物を作るからこその「脆弱性の混入」なのではないでしょうか?
そも「ここで問題になっているのは、「無駄かどうか」という議論ではないのです。あくまで、正しくデータ型・用途を理解しているかどうか、という問題なのです。」とありますが、では出力時にサニタイズすることがこの妨げになりうるのでしょうか?
もし「表示するタイミングで何が表示されるかによってデータ型の用途を理解させる」ことを目的としているのであれば、土台から根底から誤ってます。ンなモノはis系の関数なりなんなりをきちんと用いるべきです。袋の外から叩いたときの泣き声で中身を判断するような真似は間違ってもしちゃぁいけません。
もしそれが「この形はこういうものだからサニタイズは必要ない」のであれば、それは仕様変更に対してあまりにも脆弱ってぇもんです。そも、近代おぶぢぇくと指向プログラミングにおいて形なんてものがどこまで重要なのでしょう? だってモノでしょ? データなんて、全部 :-P


あと、ここ。
「文字列定数は、明らかにhtmlspecialchars()をかける必要のないものです。「無駄だから」とか、そういう発想じゃありません。そこに、攻撃の入る余地がないことも重要ですが、HTMLとしての要素を期待されることが極めて多いからです。」
んっと。「攻撃が入る余地がない」がまずNGです。もしPHPのバグで「文字列定数部分へのアタック」が可能なら? そういう発想は一つ大切です。いやまぁレアではあるんですがね。
で、それ以上に根本的に根源的に大切なこと。ここ試験に出ます(笑)。
「HTMLエレメントプログラム中に書くな!!」。
最低限の基本的な部分じゃなかかと思うんですがどげんなもんでしょうか?
ビタ1bit(byteですらない。いやまぁ電子データにビタがあるかどうかは別として)たりとて、HTML要素は書いちゃいかんです。そんなことをするからデザイン変更で面倒な思いをするとです。
それを…なにをどこからどんな風に血迷えば「HTMLとしての要素を期待されることが極めて多い」などという文面につながるのでしょうか?
ちなみにこの部分で「セキュリティ的には…」という発言には一切耳を貸しません。業務上メンテナンス/保守性を確保し、その上でセキュリティも確保する。双方は分離して語られるべきではありません。相反して分離させざるを得ないときでなお「保守性の観点からはこうだがセキュリティの観点からはこう」と、セットで語られなければならないものです。
で、保守性を前提に、HTMLをプログラム中に埋め込むなど、言語道断今後横断です。で、セキュリティ上に何らかのメリットがあるかといえば、あるようには到底思えません(あるならそれはそれで考慮されるべきだと思うのですが)。


私は「例え初心者に教えるときにですら」MVCの理念とかサニタイズの考え方とかは叩き込みます。思うに、少なくとも現在、その辺の教育は躾レベルです。一番初めに「有無を言わさず」叩き込み刷り込むべきです。
それをまがりなりにも「PHPサイバーテロの技法」という、セキュリティへの警鐘を鳴らすべく作られた書籍がこれでは…目も当てられません。
まだ書籍をちゃんと読んでいない中で恐縮ですが、高木先生の記述とGIJOE氏の記述/反論を読むに、現時点においてはGIJOE氏の発言のほうに多くの違和感を感じてしまいます。


…で終わるとこのBlogの意味がないので、まとめます(笑
サニタイズは出力直前におこなうのがガル流。サニタイズは「お客様(出力先)のお好みに合わせて」お出しいたします。
・データの形なんてものは信じちゃいけません。何時誰がどんな仕様変更するかわかったもんじゃないですし :-P
・プログラム中にHTMLなんか1bitたりとて書いてみろ、その場で(以下残虐描写につき検閲削除


こんなところでしょうか。
皆様からのご反論ご意見お待ちしております。