現在の位置: ホーム> 最新記事一覧> pdostatement :: fetchallでクエリをするときに、SQL注入攻撃を効果的に防止する方法は?

pdostatement :: fetchallでクエリをするときに、SQL注入攻撃を効果的に防止する方法は?

M66 2025-06-28

SQL注入とは何ですか?

SQLインジェクションとは、攻撃者が悪意のあるSQLコードをSQLクエリに挿入することを指し、盗み、データの改ざん、さらにはデータベースサーバーの制御の目的を達成します。たとえば、開発者がユーザーをSQLクエリステートメントに直接スプリースする場合、攻撃者は特定のSQLコードを入力してクエリロジックを変更する場合があります。

たとえば、次のクエリステートメントがあるとします。

 $sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";

攻撃者がユーザー名またはパスワードとして以下を入力した場合:

  • ユーザー名: 'または' 1 '=' 1

  • パスワード: 'または' 1 '=' 1

このクエリステートメントは次のとおりです。

 SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '' OR '1'='1';

これは通常の認証をバイパスし、攻撃者は機密データを簡単に取得できます。これを防ぐために、パラメーター化されたクエリ(準備されたステートメント)を使用して、SQLインジェクション攻撃からアプリケーションを保護できます。


PDOを使用したSQL注入を防ぎます

PDOは、SQL注入を防ぐための強力なメカニズム、つまり準備されたステートメントを提供します。前処理ステートメントでは、クエリのユーザー入力は、ユーザーが悪意のあるSQLコードを入力してもデータベースが実行されないように、SQLコードの一部としてではなくパラメーターとして扱われます。

1. PDOを使用してデータベースに接続します

まず、PDOを使用してデータベースに接続する必要があります。接続を作成するときに例外処理が有効になっていることを確認してください。これにより、エラーをより適切にデバッグできます。

 try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo "データベース接続に失敗しました: " . $e->getMessage();
}

2。前処理ステートメントを使用したクエリ

PDOの前処理ステートメントは、SQL注入を防ぐだけでなく、特に同じタイプの複数のクエリが実行された場合にクエリパフォーマンスを改善します。

ユーザーのユーザー名に基づいてユーザーデータを取得する必要があるクエリがあるとします。次のコードを使用できます。

 $sql = "SELECT * FROM users WHERE username = :username";
$stmt = $pdo->prepare($sql);

// バインドパラメーター
$stmt->bindParam(':username', $username, PDO::PARAM_STR);

// クエリを実行します
$stmt->execute();

// クエリの結果を取得します
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 出力結果
foreach ($results as $row) {
    echo "ユーザー名: " . $row['username'] . "<br>";
    echo "郵便: " . $row['email'] . "<br>";
}

上記のコードでは、ユーザー名はプレースホルダーであり、ユーザーが入力したユーザー名はBindParamメソッドを介してプレースホルダーにバインドされます。この方法により、ユーザーが何を入力しても、SQLクエリに直接スプライスされるのではなく、パラメーターとしてデータベースに渡され、SQLインジェクションが効果的に防止されます。

3. Fetchallを使用して結果を取得します

pdostatement :: fetchallメソッドは、クエリ結果を配列として返すことができます。複数のデータを取得するのに最適です。上記のコードのfetchall(pdo :: fetch_assoc)は、クエリの結果を連想配列の形式で返し、各要素はデータ行に対応します。

すべてのクエリ結果を取得したい場合は、次の方法を使用できます。

 $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

単一の行の結果のみが必要な場合は、 Fetchメソッドを使用できます。複数の行の結果を取得する場合は、 Fetchallが適切です。

4。ノートURLパラメーターを使用する場合

ユーザーの入力、特にURLパラメーターを処理するときは、事前処理ステートメントを常に使用する必要があります。たとえば、URLに特定のIDパラメーターが含まれている場合、SQLステートメントに直接スプライシングすることを避ける必要がありますが、プリプロセシングステートメントを通過します。

IDパラメーターがURLに渡されると仮定すると、次のコードを使用して安全なクエリを実行できます。

 $id = $_GET['id'];  // 得る URL 社内 id パラメーター

$sql = "SELECT * FROM users WHERE id = :id";
$stmt = $pdo->prepare($sql);

// バインドパラメーター
$stmt->bindParam(':id', $id, PDO::PARAM_INT);

// クエリを実行します
$stmt->execute();

// クエリの結果を取得します
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
  • 関連タグ:

    SQL