PHP 公式マニュアルにおける SQL インジェクションと PDO の数値の型指定のサンプルコード
PHP 公式マニュアルの SQL インジェクションのページには数値の扱い方がきちんと明記されている。
アプリケーションが、数値入力を期待している場合、データを is_numeric() で検証するか、 settype() により暗黙の型変換を行うか、 sprintf()により数値表現を使用することを検討してみてください。
サンプルコードも掲載されている。
settype($order, 'integer'); $query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;"; // フォーマット文字列の%dに注意してください。%sを使用しても意味がありません。 $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;", $offset);
ついでに書いておくと mysql_real_escape_string()
、sqlite_escape_string()
はそれぞれ mysqli_real_escape_string
や SQLite3::escapeString
に変えてほしいな。
データベースがバインド変数をサポートしていない場合は、 データベースに渡される数値以外のユーザー入力を データベース固有の文字列エスケープ関数 ( mysql_real_escape_string(), sqlite_escape_string() など) でクオートしてください。
数値の型指定の話に戻すと PDO のマニュアルでは数値の型指定が徹底されていないので、今後強化すべきと考える。
PDO のプリペアドステートメントおよびストアドプロシージャのページでは数値の型指定が行われていない。
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"); $stmt->bindParam(':name', $name); $stmt->bindParam(':value', $value); // 行を挿入します $name = 'one'; $value = 1; $stmt->execute
prepare メソッドおよび executeページでは文字列を前提とする execute
メソッドが使われている。
$sql = 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour'; $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)); $sth->execute(array(':calories' => 150, ':colour' => 'red')); $red = $sth->fetchAll();
quote のページでは数値の型指定が入ったサンプルコードが存在しない。
bindValue および bindParam のページでは数値の型指定が入ったコードが記載されている。
$calories = 150; $colour = 'red'; $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour'); $sth->bindParam(':calories', $calories, PDO::PARAM_INT); $sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);