昨日のSQLインジェクションの話、結局、どういうふうに設計すべき、修正すべきとウィリアムのいたずらの方針を書いていなかったんで、わたしは、こう考える!というのを、書いておきます。
入力データで、入力チェックをしたとしても、SQLインジェクションをはじくには、アポストロフィーをはじいてしまうか、これをエスケープするしかない。
でも、アポストロフィーをはじいていいのか?という問題がある。
たとえば、ログイン名に、メリーチョコレートだいすき!な人がいて、mary'sにしちゃったら?とか。。。
また、SQLインジェクションとして、不正アクセスであれば、ログイン名だけの話だけど、それ以外で行うことも考えると(検索でSQLインジェクションをやって、大量の検索をさせて、システムをとまらせる)、本の名前の検索などでは、アポストロフィーが入ることはある。
=でチェックを書けた場合?でも、たしか、モーニング娘。の本になかったっけ?自信ない。
(あ、ぜんぜん関係ないけど、さっき、地震あったねえ、いま、自信ないと打って気付いた)
なんで、入力ではじくというのは無理がある。
ということで、入力チェックで、このSQLインジェクションをやるのは、きつい。
じゃあ、入力の時点で、エスケープしちゃったら?っていうことになるけど、そうすると、こんど、mary'sは、mary\'sになって、文字数が変わってしまう。文字数によって、なにか処理を分けているとかいう場合、後段の処理で問題。
っていうことで、結果として、
・入力チェックは、SQLインジェクションとかを意識せず、適切に行う
・処理中の内部データはエスケープしないで、文字をそのまま処理する
・DBアクセスのところで、エスケープの変換をかけ、SQLインジェクションをはじく
→結果として、ここではずく=サニタイズしてるのとおなじ。
で、DBアクセスのところで、エスケープするのっていうのは、至極あたりまえの話だと思う。
ふつう、入出力のところは、その入出力デバイスにあった形で文字などの情報が変換されるはず。で、その入出力データを他のモジュールが利用するときは、内部表現に変換しておくる。
エスケープというのは、いわば、DB用のために文字を変えるものなので、入出力モジュールであるDBアクセスのところで、エスケープをいれる。それ以前は、内部表現として、エスケープしない、ふつうの文字の形で扱う。
これって、あたりまえの話っすよねえ。
と考えると、設計・修正は、こんなところに落ち着くんじゃないだろうか。
設計は、DBアクセスを共通化し、そのDBアクセスの中で、エスケープする。
修正するときも、DBアクセス部分に対して、エスケープ処理をいれる。
DBアクセス部分が、モジュール化(別クラス化)されていなければ、時間があれば、モジュール化する。
つまり、O/Rマッピングとか世間で入ってるけど、RDBアクセスだけでなく、入出力部分には、そもそも、インピーダンスミスマッチがあるんだから、その入出力部分をモジュール(クラス)として独立させ、それぞれ、利用可能な形に変換して(=エスケープなどを送って)対応するべきであると思う。
そうすると、SQLインジェクションは、はじけるので、べつに、入力のところで、エラーチェックをするかどうかというのは、(したほうがいいけど)今回の話にあまり関係するところでは、ないかと思う。逆に入力のところでエスケープすると、エスケープした形が内部コード表現となるので、あとの処理がそれに影響されてしまい、得策ではないと思う。
てなことを考えてます。