82

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();
}
4

2 に答える 2

98

あなたの質問に対する短い答えは「いいえ」です。

最も厳密な意味では、データベース レベルでは、準備済みステートメントは、SQL ステートメントの「値」ビットにパラメーターをバインドすることのみを許可します。

これについての 1 つの考え方は、「ステートメントの実行時にその意味を変更せずに置換できるもの」です。テーブル名は、これらの実行時の値の 1 つではありません。これは、SQL ステートメント自体の有効性 (つまり、有効な列名) を決定し、実行時にそれを変更すると、SQL ステートメントが有効かどうかが変わる可能性があるためです。

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

あなたの最善の策は、続行することです

SELECT * FROM {$mytable}

ただし、ユーザー入力からのものである場合は、最初にチェックするテーブルのホワイトリストが絶対に必要です。$mytable

于 2012-07-04T11:05:06.180 に答える
1

「データベース」を作成しようとするときも同じ規則が適用されます。

準備済みステートメントを使用してデータベースをバインドすることはできません。

すなわち:

CREATE DATABASE IF NOT EXISTS ?

動作しないでしょう。代わりにセーフリストを使用してください。

于 2018-11-08T15:08:09.460 に答える