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からの指定になります。