PHP+MySQLでSQLインジェクション対策


ここで書いてあることだけでは十分とは言えませんが、これだけでも心当たりがあるシステムがやまほどあるはずです。

mysql_set_charsetを使用する

MySQLへクエリーを発行する際に文字エンコーディングを指定する方法として、以下のような方法がよく紹介されていますが、これは間違いです。

// 誤った方法
mysql_query("set names utf8");

以下のようにmysql_set_charset()関数を使用しなければ、mysql_real_escape_string()関数が誤った文字エンコーディングを前提にしてエスケープしようとしてしまいます。

// 正しい方法
mysql_set_charset("utf8");

詳しい説明は以下のサイトなどを参考にどうぞ。

mysql_real_escape_stringを使う

addslashes()というよく似た関数もありますが、それでは不完全です。

また、mysql_set_charset()と必ずセットで使用するべきです。

header()関数等で文字エンコーディングを明確に指定する。

これは、MySQLを使っているかどうかに限らず、常に心がけるべきです。

header("Content-type: text/html; charset=UTF-8");

header()関数ではなく、php.iniやhttpd.confでもデフォルトのエンコーディングを指定できますので、可能な場合はそちらも使用した方がベターです。

mb_convert_encoding()にautoを使用しない

可能であれば、mb_convert_encoding()に指定する変換前のエンコーディングはautoにしないで明示的に指定しましょう。

header()関数やphp.iniなどで出力エンコーディングを明示的にクライアントに知らせてあげれば、まっとうなブラウザなら期待通りのエンコーディングで返してくれます。

また、以下のような記述を入れて不正な文字エンコーディングを検出したらその後の処理を中断するべきです。

function check_encoding($key, $value) {
  if (!mb_check_encoding($value, 'UTF-8')) {
    die('不正な文字コード');
  }
}

array_walk_recursive($array, 'check_encoding');

内部エンコーディングにSJISを使用しない

これは論外。
某有名SNSのPHP関連のコミュニティで、SJISを使うという回答がかなり多くてびびりました。

PHPのマニュアルにも以下のような記載があります。

注意: SJIS, BIG5, CP936, CP949, GB18030 は、読者がパーサ/コンパイラ、 文字エンコーディングと文字エンコーディングの問題点について精通していない限り 内部エンコーディングとして使用するべきではありません。

検証していませんが、mb_real_escape_string()も期待通り動くかどうか怪しいですし、EUC-JPやUTF-8を使用すれば、そんな検証をする必要もありません。

てっとりばやく使えるPHPだからこそマニュアルには従うべきですよね。

その他

できれば、プリペアードSQLを使うのがベターなのですが。。。
まだ怪しいかんじなのでMySQLに関しては使ってないです。

ところで。。。

テーマファイルを変えてみました。


関連する記事

コメントを残す

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

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>