「SET NAMES」って禁止だったの?

【この記事の所要時間 : 約 4 分

canalize.jp – 環境が異なるサーバーへのアプリケーション移行

現象:
PHPで表示した2バイト文字が画面上で文字化けしている。
原因:
MySQLを4.0.2から5.0.22にアップデートしたため、文字コードが自動変換されてSQL文がSJISで発行されていなかったため。
対策:
SQL文を発行する前に「SET NAMES SJIS」を発行し、SQL文をSJISで発行するように修正。(phpMyAdminは、内部的に指定された言語&エンコーディングにしたがって「SET NAMES ○○」を呼んでいるためphpMyAdmin上では文字化けしていなかったみたい)
結果:
文字化けせずに表示された。
補足:
・文字コードを確認するSQL文「SHOW VARIABLES LIKE ‘char%’;」
・MySQL4.1以上対応のアプリは、必ず”SET NAMES キャラクターセット名”というSQL文をサーバーに接続した直後に実行すること。

という風に以前、文字化け対策として、「SET NAMES」を利用しよう!なんていうことを書いてたが、以下のブログには、SQLインジェクション対策のために「SET NAMES」は禁止だ!ということが書かれてあるのを見つけた。
yohgaki’s blog – SET NAMESは禁止

MySQLには文字エンコーディングを変更する「SET NAMES」SQL文が用意されています。(PostgreSQLも同様のSQL文、SET CLIENT_ENCODINGがあります)この機能はSQLコンソールからは使ってよい機能ですが、アプリケーションからは使ってはならない機能です。 SQLインジェクションに脆弱になる場合があります。
Ruby on Railsの本を読んでいて、ActiveRecordを説明している部分にMySQLの文字エンコーディングを変更する場合の例としてSET NAMESが利用されていました。アプリケーションからはSET NAMESは使ってはならない事を周知させるのは結構時間が必要かなと思いました。
PHPも5.2の途中からMySQLモジュールにlibmysqlの文字エンコーディング設定APIのラッパー関数が追加されていたりするので、たまたま最近読んだRoRの本だけでなく、多くの開発向け情報ソースにSET NAMESを利用した例が載っていると思います。
ストアドプロシージャだけ使っていれば安全ですが、アプリケーションからDBMSの文字エンコーディングを設定する場合、SQL文ではなく必ず文字エンコーディング設定APIを利用するよう紹介しなければならないです。MySQL4はストアドプロシージャが使えないので、フレームワークなどではエミュレートしています。ストアドプロシージャだけ使って防御している「つもり」で防御になっていない場合もあります。これもフレームワークを使っていてもアプリケーションが脆弱になる良い例ですね。
脆弱性の説明は面倒ですが注意事項は簡単です。「DBMSをアプリケーションから利用する場合、文字エンコーディング設定は必ずAPIを利用する」つまり「SET NAMES(SET CLIENT_ENCODING等も)は禁止」です。

文字エンコーディング設定APIなるものがあるのを知らなかった。
ちょっと調べてみようっと。

基礎からのMySQL 改訂版 (プログラマの種シリーズ SE必修! )
西沢 夢路
ソフトバンククリエイティブ
売り上げランキング: 54,557
スポンサーリンク
レクタングル(大)広告
  • このエントリーをはてなブックマークに追加
スポンサーリンク
レクタングル(大)広告

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です