MySQLプリペアードステートメントは、インジェクションを防止するための推奨される方法です。
MySQL のプレコンパイルされたステートメントには、プリペアドステートメントとストアドプロシージャの 2 種類の使用方法があります。
- プリペアードステートメントの使用:プリペアードステートメントは、アプリケーションとデータベース間で実行されるメカニズムで、SQLクエリ文とパラメータを分離し、まずプリペアードステートメントをデータベースに送信してからパラメータを送信します。この方法はSQLインジェクション攻撃を防ぐことができます。パラメータの値はクエリ文に直接連結されるのではなく、プレースホルダという形でデータベースに渡されるからです。パラメータの値はデータベースで処理され、エスケープされるため、注入攻撃を効果的に防ぐことができます。
例えば、PHPにおけるプリペアドステートメントを用いたサンプルコード例を以下に示す。
// 创建预处理语句
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username');
// 绑定参数
$stmt->bindParam(':username', $username);
// 执行查询
$stmt->execute();
// 获取结果
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
上の例では、プレースホルダーとしてコロン(:)を使用することで、パラメーター:username がプレースホルダーとしてプリペアドステートメントにバインドされています。これにより、クエリ文とパラメーターの値が分離され、パラメーターの値が正しく処理およびエスケープされるようになります。
- ストアドプロシージャを使用する:ストアドプロシージャは、データベースに格納され、アプリケーションから呼び出せる、プリコンパイルされた SQL ステートメントの集合です。ストアドプロシージャはパラメータを受け取り、SQL インジェクション攻撃を防ぐために、実行中にパラメータを処理してエスケープします。ストアドプロシージャを呼び出して SQL クエリを実行すると、SQL ステートメントを直接接続するリスクを軽減できます。
例えば、MySQLではストアドプロシージャを作成するサンプルコードは次のようになります。
CREATE PROCEDURE getUser(IN username VARCHAR(255))
BEGIN
SELECT * FROM users WHERE username = username;
END;
上記の例では、パラメータであるusernameをストアドプロシージャの入力パラメータとして指定し、実行時にクエリでそのパラメータを使用することで、SQL文を直接結合するリスクを回避できます。ストアドプロシージャは実行時にパラメータの値を処理してエスケープするため、インジェクション攻撃を防ぐことができます。