PEAK XOOPS - SQL用文字列エスケープにどの関数を使うべきか in englishin japanese

Archive | RSS |
PHP
PHP : SQL用文字列エスケープにどの関数を使うべきか
Poster : GIJOE on 2006-05-25 06:34:07 (18473 reads)

in englishin japanese
最近、ELFさんとSQLにおける文字列エスケープ方法について議論をかわしたのですが、それが面白かったのでここにメモしておきます。

私自身はaddslashes()派です。その理由は以下のようなものです。

(A) 速度
(B) magic_quotes_gpc 環境との親和性
(C) 逆変換関数が存在する
(D) コネクションの有無に依らず利用可能
※とはいいつつ、コネクションがなければ利用できないのって、mysql_real_escape_string()くらいか?
※※ DBエンジンをMySQLとPostgreSQLで交換してもソースコードがそのまま流用できる、というメリットはあえて外してあります。

ELFさんはこれに対して、*_escape_string()派です。その理由はこちら。

(1) やろうとしていることが一目でわかる.マニュアルも引いても関数を使う意図がわかる
(2) grepでエスケープしているところを調べられる.関数名が変わってもsedですぐに置換できる
(3) 将来エスケープが変更されるのではなく拡張されることがあってもあわせてくれることをそれに期待できる

さらに、(B)への反論として、magic_quotes_gpc環境なんて自分が管理するサーバではあり得ないし、他者が管理するサーバであれば、magic_quotes_sybase=on環境だってあり得る、というのもありました。

さすがはELFさん。(1)〜(3)とも理にかなっています。最初、(1)や(2)については、私から「addslashes()だってSQL用の文字列エスケープ以外に用途なんてないでしょ」とか反論しましたが、ELFさんに、PHPソースコードを吐き出す場合などに、addslashes()を使う可能性を指摘され、納得しました。

ちなみに、(B)については、バックグラウンドの違いかな、という気はします。私自身、magic_quotes_gpc環境なんて駄目駄目だとは思いますが、想像以上に、デフォルトがmagic_quotes_gpc=onとなっているホスティングサービスは多いのです。(逆に、デフォルトでmagic_quotes_sybase=on環境のホスティングサービスは聞いたことありません)

ただそれでも今後、私自身が、addslashes()を使い続けていくだろうなあ、と思える理由が一つだけあります。それは、大垣さんへの反論(addslashes()関数を使うことそのものが脆弱性につながるわけじゃない、という主張)を行うために、addslashes()の動作を徹底的に追った経験があるからです。このおかげで、addslahse()が、どの文字がどのようにエスケープするかをソースコードレベルで正確に把握できました。
※ちなみに私は、大垣さんを尊敬してます。単にaddslashes()に関して意見が違うだけです。

ごく最近私が見つけた某プロジェクトのSQL Injectionも、`(バッククオート)も'(シングルクオーテーション)と同様にエスケープされる、なんて勘違いがベースにあったように思えます。エスケープ処理の変換ルールを正確に知っていれば、このような勘違いは防げたわけで、両関数の細かなメリット・デメリット論よりも、「より使い慣れたツール(関数)を使う」ことの方が重要なのかもしれません。

もちろん、PHPってものは、メンテナが変わった途端、ソースコードががらりと変わることもあるのでそのあたり信用しきるのは危ないのですが、それは*_escape_string()も同じでしょう。

ちなみに上の話はすべて、MySQLかPostgreSQLに限った話です。Sybaseで駄目なのは有名ですし、SQLiteにおいてもaddslashes()による文字列エスケープは明確に非推奨とされています。

Printer friendly page Send this story to a friend

Comments list

GIJOE  Posted on 2006/5/26 5:15 | Last modified
Quote:
SQL文に対するリテラルのエスケープに関しては、セキュリティとかINJECTIONなんて概念が一般的になる前でも、プログラマに対して「正しくプログラムを動作させる為に必要」って教育がされますから。

それはおっしゃる通りで、SQLの基本中の基本ですよね。
SQL Injection対策の「サニタイズ」でないことは明らかです。

このあたり、ちゃんと書いたつもりだったのに、読み返した「サイバーテロ本」では、そういう記述がどこにもなかったのには自分でも愕然としました。
確かに高木浩光氏に突っ込まれても仕方ないでしょう。

ただ、SQL Injectionとなる理由って2つありますよね。

・リテラルのエスケープし忘れ
・リテラルではない要素をSQLへ導入する

この後者のミスの方がむしろ怖いんじゃないかと思うんです。
後者の手抜きパターンとして、ORDER BY のカラム名を直指定して、ホワイトリストチェックなんてのがありますが、それは「サニタイズ」と言えなくもないでしょう。

…って全然違う話題で恐縮ですが。


いずれにせよ、PHP史的に、addslashes()の元々の用途が違うのだから、SQL用エスケープに利用すべきではない、という意見は傾聴する価値がありますね。


Quote:
余談ですが、PHPに関しては、簡易WEB作成ツールって位置付けで発祥した為かmagic_quote_gpcなんてのが最初から用意されていたがために、余計に混乱をもたらしているような気がします。これがために、少し前にはmagic_quote_gpc環境で無い場合にすべてのGPCに addslashesなんて処理が行われていた物もあったりします。
なるほど〜。
PHPはスタート地点からまともなプログラミング言語とは違うんですね。
magic_quotes_gpcも regiter_globals と同じく、過去の遺物なんでしょうね。
nobunobu  Posted on 2006/5/25 7:56
Quote:
`(バッククオート)も'(シングルクオーテーション)と同様にエスケープされる、なんて勘違いがベースにあったように思えます。
そもそも、addslashesの用途がINJECTION対策なんて意識が薄かった(無かった?)のだと思いますよ。
単純にSQL文中のリテラルの中に、クォーテーション文字が使われる可能性があるから、SQLエラーおこさないためには、エスケープの必然があって、
昔のMySQLの識別子で許されている文字が「英数字」と‘_’ と ‘$’ に限定されていたのでエスケープの必然が無いって意識がベースにあったのだと思います。
SQL文に対するリテラルのエスケープに関しては、セキュリティとかINJECTIONなんて概念が一般的になる前でも、プログラマに対して「正しくプログラムを動作させる為に必要」って教育がされますから。

余談ですが、PHPに関しては、簡易WEB作成ツールって位置付けで発祥した為かmagic_quote_gpcなんてのが最初から用意されていたがために、余計に混乱をもたらしているような気がします。これがために、少し前にはmagic_quote_gpc環境で無い場合にすべてのGPCにaddslashesなんて処理が行われていた物もあったりします。
Login
Username or e-mail:

Password:

Remember Me

Lost Password?

Register now!