読者です 読者をやめる 読者になる 読者になる

WebEngine

web、プログラミング関係について書いていきます。あなたの優しい眼差しがブログの成長につながりますのでどうぞよろしく。

SQLインジェクション対策の一歩としてプレースホルダを利用する

MySQL php SQL

そもそもSQLインジェクションとは?

悪意を持ったユーザが入力フォームなどにSQLを打ち込んで、不正に データベース(以下DB)にアクセスすること。XSSクロスサイトスクリプティング)に次いで 有名な攻撃手法とも言われます。
この攻撃を受けると・・・

  • DB内部の情報が許可したユーザ以外の人物に取得される。
  • DB内部のデータが変更させられる。
  • 認証を回避される(IDとパスワードなしでログインされるなど)

などの被害を受けます。DBは個人情報を扱うことが多いので、 公開するアプリケーションは必ずチェックしなければならない項目の 一つです。


プレースホルダには2種類ある

動的プレースホルダと静的プレースホルダです。なにが違うかと 言うと・・・

  • 動的 > 値のバインドをアプリケーション側で実行
  • 静的 > 値のバインドをDB側で実行

バインドとは、「割り当てる」という意味です。
よくわからないという方はとりあえず静的を選択しましょう。簡単に言うと、 静的プレースホルダは、プレースホルダの状態でSQL文がDBへ送られるので、あとから SQL文が変更される可能性が減るのです。

静的プレースホルダの設定の仕方

※ ここではMySQL、かつPDOで接続する場合について説明します。

プレースホルダの設定は、デフォルトで動的になっています。なので、 動的を使用する場合には、特に設定の必要はありません。
静的プレースホルダを使用する場合は、下記のようにします。

PDO::ATTR_EMULATE_PREPARES => false

ほかの設定とまとめたい場合は、こういう書き方もできます。

$pdo = new PDO(
  "mysql:host=localhost; dbname=hogehoge",
  "username",
  "password",
  [
    PDO::ATTR_EMULATE_PREPARES => false
  ]
);


値のバインドの仕方

ここでは実用性を考慮して関数にしてみました。引数で渡された$idNumberと tablenameのidで一致するものがあれば、すべて取り出して$infoに入れるという ものです。最終的には情報の入った$infoを返します。

function searchID($idNumber) {
  $stmt = $pdo->prepare('SELECT * FROM tablename WHERE id = ?');
  $stmt->bindValue(1, $idNumber, PDO::PARAM_INT);
  $stmt->execute();
  $info = $stmt->fetchAll();
  return $info;
}

見てのとおり、「?」の部分に値がバインドされます。バインドの指示を出しているのは次の行。

$stmt->bindValue(1, $idNumber, PDO::PARAM_INT);

最初の引数が何番目の「?」かという情報。2番目の引数がバインドする値、3番目が 数値か文字列か判別する引数です。例ではIDなので数値を採用しています。文字列は、

PDO::PARAM_STR

と指定します。
注意すべきなのが、何番目の「?」か、というところです。プログラミングに慣れている人 は「最初なら0じゃないか?」と思われるかもしれませんが、1からの指定になります。