ホームページ >データベース >mysql チュートリアル >PHP アプリケーションでの SQL インジェクションを防ぐにはどうすればよいですか?
PHP での SQL インジェクションを防止
SQL インジェクションは、変更されていないユーザー入力が SQL クエリに誤って挿入された場合に発生する脆弱性です。これにより、攻撃者が任意の SQL コードを実行できるようになり、アプリケーションに壊滅的な影響を与える可能性があります。
SQL インジェクションを防ぐには、データを SQL から分離し、データが常にデータとして残り、SQL パーサーによってコマンドとして解釈されないようにすることが重要です。これは、パラメータを指定したプリペアド ステートメントを使用することで実現できます。これにより、SQL クエリがデータベース サーバーに送信され、パラメータとは別に解析されます。これにより、攻撃者は悪意のある SQL を挿入できなくなります。
これを実現するには 2 つの方法があります:
<code class="language-php">$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name'); $stmt->execute(['name' => $name]); foreach ($stmt as $row) { // 处理 $row }</code>
PHP 8.2:
<code class="language-php">$result = $db->execute_query('SELECT * FROM employees WHERE name = ?', [$name]); while ($row = $result->fetch_assoc()) { // 处理 $row }</code>
PHP 8.1 以前:
<code class="language-php">$stmt = $db->prepare('SELECT * FROM employees WHERE name = ?'); $stmt->bind_param('s', $name); // 's' 指定变量类型 -> 'string' $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // 处理 $row }</code>
MySQL 以外のデータベースに接続している場合は、2 番目のドライバー固有のオプション (PostgreSQL の pg_prepare()
および pg_execute()
など) を参照できます。 PDO は普遍的な選択肢です。
正しい接続構成
PDO を使用して MySQL データベースにアクセスする場合、デフォルトでは実際のプリペアド ステートメントは使用されません。この問題を解決するには、準備されたステートメントのシミュレーションを無効にする必要があります。 PDO を使用して接続を作成する方法の例を次に示します:
<code class="language-php">$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8mb4', 'user', 'password'); $dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);</code>
MySQLi の場合、同じ操作を実行する必要があります:
<code class="language-php">mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // 错误报告 $dbConnection = new mysqli('127.0.0.1', 'username', 'password', 'test'); $dbConnection->set_charset('utf8mb4'); // 编码</code>
説明
prepare
に渡す SQL クエリは、データベース サーバーによって解析され、コンパイルされます。パラメーター (?
または上記の :name
の例のような名前付きパラメーター) を指定することで、何に基づいてフィルターするかをデータベース カーネルに伝えます。次に、execute
が呼び出されると、前処理されたクエリが指定したパラメーター値と結合されます。
パラメータ値は SQL 文字列ではなく、コンパイルされたクエリと結合されることが重要です。 SQL インジェクションは、データベースに送信する SQL を作成するときに、スクリプトをだまして悪意のある文字列を含めることによって機能します。したがって、実際の SQL をパラメータとは別に送信することで、予期しない結果が得られるリスクを軽減できます。
準備されたステートメントを使用して送信されたパラメーターはすべて、単純に文字列として扱われます (ただし、データベース カーネルは最適化を実行するため、パラメーターが数値である場合もあります)。上の例では、変数 $name
に 'Sarah'; DELETE FROM employees
が含まれている場合、結果は検索文字列 "'Sarah'; DELETE FROM employees "
のみとなり、テーブルはクリアされません。
準備されたステートメントを使用するもう 1 つの利点は、同じセッション内で同じクエリを複数回実行する場合、解析とコンパイルが 1 回だけで済むため、速度が向上することです。
以上がPHP アプリケーションでの SQL インジェクションを防ぐにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。