ホームページ >バックエンド開発 >PHPチュートリアル >プリペアドステートメントはどのようにして PHP での SQL インジェクションを防ぐことができますか?
適切な予防措置を講じずにユーザー入力を SQL クエリに統合すると、SQL インジェクションに対するコードの脆弱性が発生します。次の脆弱なコード スニペットを考えてみましょう。
$unsafe_variable = $_POST['user_input']; mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");
このシナリオは、値') などのユーザー入力文字列を介して悪用される可能性があります。 DROP TABLE テーブル;--、悪意のあるクエリにつながります:
INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')
このような攻撃を回避するには、データを SQL から分離し、データがデータとして扱われるようにすることが不可欠です。 SQL パーサーによってコマンドとして解釈されません。パラメータ化されたクエリを含むプリペアド ステートメントは、SQL ステートメントとパラメータ値を分離する堅牢なソリューションを提供します。データベース サーバーは SQL ステートメントを解析してコンパイルし、パラメータを文字列として扱い、悪意のある SQL インジェクションの試みを効果的にブロックします。
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name'); $stmt->execute([ 'name' => $name ]); foreach ($stmt as $row) { // Do something with $row }
$result = $db->execute_query('SELECT * FROM employees WHERE name = ?', [$name]); while ($row = $result->fetch_assoc()) { // Do something with $row }
$stmt = $db->prepare('SELECT * FROM employees WHERE name = ?'); $stmt->bind_param('s', $name); // 's' specifies the variable type => 'string' $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // Do something with $row }
デフォルトでは、PDO はエミュレートされたプリペアド ステートメントを使用します。エミュレーションを無効にして、MySQL に対して真のプリペアド ステートメントを強制するには、次のように設定します。
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
同様に、次のように設定します。
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // error reporting $dbConnection = new mysqli('127.0.0.1', 'username', 'password', 'test'); $dbConnection->set_charset('utf8mb4'); // charset
準備されたステートメントは、実行時にデータベース サーバーによって解析およびコンパイルされます。パラメーターは、フィルターを適用する場所をデータベース エンジンに通知します。値を指定して準備されたステートメントを実行すると、コンパイルされたステートメントは SQL 文字列ではなく、それらの値と結合されます。これにより、意図しない SQL 実行につながる可能性のある悪意のある文字列の挿入が防止されます。
準備されたステートメントは、クエリ構造が変更される動的クエリには適していません。このような場合、可能な値を制限するホワイトリスト フィルターを使用する必要があります。
以上がプリペアドステートメントはどのようにして PHP での SQL インジェクションを防ぐことができますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。