SQL インジェクションを防止する最善の方法は、現在のテクノロジを使用することです。MySQLmysql_
ファミリの関数は非推奨であり、将来のリビジョンで PHP から削除される予定です。
代わりに、MySQLi または PDO で準備済みステートメントを使用する必要があります。
これらのテクノロジでは、準備されたステートメントとパラメーター化されたクエリが使用されます。SQL ステートメントは、データベース サーバーによってパラメーターとは別に解析されます。攻撃者が悪意のある SQL を挿入することは不可能です。
これを実現するには、基本的に 2 つのオプションがあります。
MySQLi :
$stmt = $dbConnection->prepare('SELECT * FROM table WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
PDO :
$stmt = $pdo->prepare('SELECT * FROM table WHERE name = :name');
$stmt->execute(array(':name' => $name));
foreach ($stmt as $row) {
// do something with $row
}
何が起こるかというと、渡した SQL ステートメントがprepare
データベース サーバーによって解析およびコンパイルされます。パラメーター (?
または のような名前付きパラメーター:name
) を指定することにより、データベース エンジンに何をフィルター処理するかを伝えます。次に、準備されたステートメントを呼び出すexecute
と、指定したパラメーター値と組み合わされます。
ここで重要なことは、パラメーター値が SQL 文字列ではなく、コンパイルされたステートメントと結合されることです。SQL インジェクションは、スクリプトが SQL を作成してデータベースに送信するときに、悪意のある文字列を含めるようにスクリプトをだますことによって機能します。したがって、実際の SQL をパラメーターとは別に送信することで、意図しない結果になるリスクを制限できます。プリペアド ステートメントを使用するときに送信するパラメータはすべて文字列として扱われます (ただし、データベース エンジンが最適化を行う場合があるため、パラメータももちろん数値になる可能性があります)。