1. ホーム
  2. php

[解決済み] プリペアドステートメントでテーブル名をパラメータ化することはできますか?

2023-06-15 21:48:17

質問

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 文の "values" ビットにパラメータをバインドすることのみが許可されます。

これを考える1つの方法は、ステートメントの実行時にその意味を変えることなく代用することができるもの"です。テーブル名は SQL 文自体の有効性 (すなわち、どの列名が有効であるか) を決定し、実行時に変更すると SQL 文が有効であるかどうかが潜在的に変わってしまうため、これらの実行時の値の 1 つではありません。

もう少し高いレベルでは、PDOのような、実際にプリペアドステートメントをデータベースに送信するのではなく、プリペアドステートメントのパラメータ置換をエミュレートするデータベースインターフェースにおいてさえ、どこでもプレースホルダを使用できる可能性があります(これらのシステムではデータベースに送信する前にプレースホルダが置き換えられるため)、テーブルプレースホルダの値は文字列になり、データベースに送信するSQL内でそのように囲まれます、したがって、次のようになります。 SELECT * FROM ?mytable を指定した場合、実際に送信されるのは SELECT * FROM 'mytable' を送ることになり、これは無効なSQLです。

最善の策は、そのまま

SELECT * FROM {$mytable}

しかし 絶対に が発生した場合に最初にチェックするテーブルのホワイトリストを持っている必要があります。 $mytable がユーザー入力から来る場合、最初にチェックするテーブルのホワイトリストを持つべきです。