なぜPHPアプリにセキュリティホールが多いのか?

http://gihyo.jp/dev/serial/01/php-security/0042
巷で叩かれていますね。
この記事読んでも、それでもオレはバインド変数を使用して無害化はJDBCドライバに任せるべきだと思うけどね。漏れるもの。サニタイズエスケープだと。RDBMSによって対象の文字も変わるしさ。
Javaで言うPreparedStatementだとテーブル名や列名がバインド変数にできない、というのと、だからPreparedStatementじゃなくてサニタイズエスケープ、っていうのはちょっと話が違うんじゃないかと思った。


ところでテーブル名とかカラム名を変数化して外から渡された値をそのまま使うような要件・必要性ってあるんだろうか? そして仮にそんな要件があったとしても、外から渡されたパラメタを(サニタイズの有無にかかわらず)そのまま使うってのはいかがなものかと思うのだが。
まずテーブルを外から指定した値にする場合、列名もWHERE句もORDER BY句も変わる可能性が高いわけで、そうなるとSQL自体組み直しになりますよ。テーブル名をを引数で受け取ってそのままSQLに放り込むという設計自体がまずいような気がするな。それってセキュリティと言うよりそもそもおかしいんじゃないか、っていう。
一方でカラム名の場合はテーブル名よりは要件が思いつくかな。例えばプロ野球の打撃成績とか、「打率昇順降順」「本塁打昇順降順」が画面から指定できます、的な機能の場合にこの手の実装になるのだろう。
でもやっぱりこれも、画面やServletなど、HTTP REQUESTのパラメタを直接DBアクセスのクラスに引数で渡してそのまま使用するって、その設計がまずいんじゃないかね。HTTP REQUESTから渡されるパラメタの中身なんていかようにも改ざんできるから、存在しないカラムや、害のある記述が、ORDER BYの後に来る可能性がありますわね。
だったら実際にSQLに配備する列はDBアクセスするクラス内に定義して、外からは、打率なら1、本塁打なら2のように*1、数字*2だけを渡すようにした方がよろしいんじゃないかしら、という気はしますわね。きれいではないけどさ。数字を改ざんされたら、想定しないパラメタでエラーにするか、デフォルトの表示順にしてしまうとか。
それか、順番変更はORDER BYでやるんじゃなくてjQueryのtablesorter*3を使って画面上でやっちゃうとかね。
まぁオレはPHPやらないので、PHP「ならでは」の事象もあるかもしれん。


(追記)
ockeghemの中の人と、yohgakiの中の人の議論で、「列名やテーブル名のホワイトリスト化」という案が出てる。これならオレみたいに1とか2とかわけのわからない数字を使う必要はないし、いいかも。
でもなんにしても外からテーブル名とか列名を渡すって行為自体、避けるべきな気がします。テーブル構造や列名がばれるのもいやだし。

*1:enumとか定数とかその辺の工夫入るけど

*2:むしろ文字として扱った方がいいとは思うけど

*3:http://tablesorter.com/docs/