ホームページ >データベース >mysql チュートリアル >SQL インジェクションを防ぐために、準備されたステートメントでパラメータ化されたテーブル名を安全に使用するにはどうすればよいでしょうか?
プリペアドステートメント内のパラメータ化されたテーブル名: ジレンマ
mysqli_stmt_bind_param は SQL インジェクションからの保護に効果的であることが証明されていますが、変数が影響を与える場合には制限に遭遇します。テーブル名が関係します。提供されたコード スニペットに示すように:
function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ) { $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
$new_table の問題のある連結により、SQL インジェクションに対する脆弱性が生じます。次のスニペットに示すように、これを別のプレースホルダーに置き換えようとすると失敗します。
function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ) { $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
プリペアド ステートメントの制限
中心的な問題は、それができないことにあります。テーブル名など、SQL ステートメントの構造を定義するパラメーターを保護するための準備されたステートメントの。これは、準備されたステートメントでは、ステートメントの意味を変更しない値のパラメーターのみが許可されるためです。テーブル名は SQL ステートメントの有効性を決定するため、実行中にテーブル名を変更するとテーブルが無効になる可能性があります。
データベースに送信する前にパラメータを置換してプリペアド ステートメントをエミュレートする PDO のようなデータベース インターフェイスを使用した場合でも、プレースホルダー値は依然として残ります。 SQL ステートメント内に囲まれた文字列。その結果、SELECT FROM ? mytable をパラメータとして使用すると、最終的に SELECT FROM 'mytable' がデータベースに送信され、無効になります。
リスクの軽減
最も安全なアプローチは依然として残っています文字列内で $mytable を使用しますが、ユーザー入力がチェックされるテーブルのホワイトリストを伴う必要があります。これにより、悪意のある攻撃者が任意のテーブルで SQL ステートメントを実行するのを防ぎます。したがって、次のコードは安全な実装を示しています:
if (whitelisted_tables($mytable)) { $statement = $mysqli->prepare("INSERT INTO $mytable VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
以上がSQL インジェクションを防ぐために、準備されたステートメントでパラメータ化されたテーブル名を安全に使用するにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。