ユーザー入力を何も変更せずに SQL クエリに直接挿入すると、アプリケーションは SQL インジェクション攻撃に対して脆弱になります。これを防ぐには、SQL からデータを分離して、データがデータとして残り、SQL パーサーによって決してコマンドとして解釈されないようにすることが重要です。
最も効果的な解決策
SQL インジェクション攻撃を回避するために推奨されるアプローチは、使用されているデータベースに関係なく、プリペアド ステートメントとパラメータ化されたステートメントを使用することです。クエリ。これらは、パラメータとともにデータベース サーバーによって個別に解析される SQL ステートメントです。このアプローチにより、攻撃者は悪意のある SQL を挿入できなくなります。
PDO または MySQLi を使用した実装
PDO は、サポートされているすべてのデータベース ドライバーに汎用のソリューションを提供しますが、MySQLi は特殊です。 MySQL へ。
$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 string type $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // Do something with $row }
正解繋がりセットアップ
MySQL に PDO を使用する場合は、エミュレーションを無効にして実際のプリペアド ステートメントが使用されていることを確認してください。
$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);
MySQLi の場合は、次を使用します:
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 サイトの他の関連記事を参照してください。