mysql_real_escape_string

SQL 文中で用いる文字列の特殊文字をエスケープする

警告

この拡張モジュールは PHP 5.5.0 で非推奨になり、PHP 7.0.0 で削除されました。 MySQLi あるいは PDO_MySQL を使うべきです。詳細な情報は MySQL: API の選択 を参照ください。 この関数の代替として、これらが使えます。

  • mysqli_real_escape_string
  • PDO::quote

説明

string mysql_real_escape_string(string $unescaped_string, resource $link_identifier = NULL)

現在の接続の文字セットで unescaped_string の特殊文字をエスケープし、 mysql_query で安全に利用できる形式に変換します。バイナリデータを挿入しようとしている場合、 必ずこの関数を利用しなければなりません。

mysql_real_escape_string は、MySQL のライブラリ関数 mysql_real_escape_string をコールしています。 これは以下の文字について先頭にバックスラッシュを付加します。 \x00, \n, \r, \, ', " そして \x1a.

データの安全性を確保するため、MySQL へクエリを送信する場合には (わずかな例外を除いて)常にこの関数を用いなければなりません。

警告

セキュリティ: デフォルトの文字セット

サーバーレベルで設定するなり API 関数 mysql_set_charset を使うなりして、 文字セットを明示しておく必要があります。この文字セットが mysql_real_escape_string に影響を及ぼします。詳細は 文字セットの概念 を参照ください。

パラメータ

unescaped_string

エスケープされる文字列。

link_identifier

MySQL 接続。指定されない場合、mysql_connect により直近にオープンされたリンクが指定されたと仮定されます。そのようなリンクがない場合、引数を指定せずに mysql_connect がコールした時と同様にリンクを確立します。リンクが見付からない、または、確立できない場合、E_WARNING レベルのエラーが生成されます。

戻り値

成功した場合にエスケープ後の文字列、失敗した場合に false を返します。

エラー / 例外

MySQL 接続が存在しない状態でこの関数を実行すると、 E_WARNING レベルのエラーが発生します。 この関数は、MySQL 接続が確立した状態でのみ実行するようにしましょう。

例1 単純な mysql_real_escape_string の例

<?php
// 接続
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
    OR die(mysql_error());

// クエリ
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
            mysql_real_escape_string($user),
            mysql_real_escape_string($password));
?>

例2 mysql_real_escape_string には接続が必須であることを示す例

この例では、MySQL 接続が存在しない状態でこの関数を実行したときにどうなるかを示します。

<?php
// まだ MySQL に接続していません

$lastname  = "O'Reilly";
$_lastname = mysql_real_escape_string($lastname);

$query = "SELECT * FROM actors WHERE last_name = '$_lastname'";

var_dump($_lastname);
var_dump($query);
?>

上の例の出力は、 たとえば以下のようになります。

Warning: mysql_real_escape_string(): No such file or directory in /this/test/script.php on line 5
Warning: mysql_real_escape_string(): A link to the server could not be established in /this/test/script.php on line 5

bool(false)
string(41) "SELECT * FROM actors WHERE last_name = ''"

例3 SQL インジェクション攻撃の例

<?php
// $_POST['password'] をチェックしなければ、このような例でユーザーに望みどおりの情報を取得されてしまう
$_POST['username'] = 'aidan';
$_POST['password'] = "' OR ''='";

// データベース上のユーザーに一致するかどうかを調べる
$query = "SELECT * FROM users WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'";
mysql_query($query);

// MySQL に送信されたクエリは、
echo $query;
?>

MySQL に送信されたクエリは次のとおり:

SELECT * FROM users WHERE user='aidan' AND password='' OR ''=''

これでは、パスワードを知らなくても誰でもログインできてしまいます。

注意

注意:

mysql_real_escape_string を利用する前に、MySQL 接続が確立されている必要があります。もし存在しなければ、 E_WARNING レベルのエラーが生成され、false が返されます。link_identifier が指定されなかった場合は、 直近の MySQL 接続が用いられます。

注意:

この関数を用いてデータをエスケープしなければ、クエリは SQL インジェクション攻撃 に対しての脆弱性を持ったものになります。

注意: mysql_real_escape_string%_ をエスケープしません。 MySQL では、これらの文字を LIKE, GRANT, または REVOKE とともに用いることで、 ワイルドカードを表現します。

参考

  • mysql_set_charset
  • mysql_client_encoding