2012-07-03 19 views
41

私は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(); 
} 
+2

いいえ、パラメータ化されたクエリは、パラメータ値をクエリ文字列にドロップするだけではなく、RDBMSにパラメータ化クエリとパラメータを別々に提供します。しかし、このようなクエリは、パラメータとしてテーブル名またはフィールド名を持つことはできません。これを行う唯一の方法は、すでに行ったようにテーブル名をクエリ文字列に動的にコード化することです。この文字列が攻撃の可能性がある場合は、最初に検証する必要があります。許可されたテーブルのホワイトリストリストなどに対して適用されます。 – MatBailie

+0

mysqli拡張の使用は安全です、先に進んでください!しかし、あなたのすべての文字列を浄化し、検証することを忘れないでください。 – B4NZ41

+0

サニタイズするのに好きな機能は何ですか? – GK1667

答えて

57

あなたの質問への短い答えは「ノー」である:このまたはこの何らかの形のよう

データベースレベルでは、プリペアドステートメントでは、SQL文の「値」ビットにのみパラメータをバインドできます。

この考え方の1つの考え方は、「実行時に文の実行時にその意味を変えずに置き換えることができるもの」です。テーブル名はランタイム値の1つではなく、SQL文そのものの有効性(つまり、有効なカラム名)を判断し、実行時に変更するとSQL文が有効かどうかが変わる可能性があります。

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

あなたの最善の策は、ちょうど

SELECT * FROM {$mytable} 

を継続することですが、あなたは絶対にはその$mytableは、ユーザの入力から来ている場合は、最初のチェック対象のテーブルのホワイトリストを持っている必要があります。

+0

大きな助言がありますが、私の経験上、これはより大きな動的ウェブサイトには当てはまりません。サイトにマルチユーザー設定があり、頻繁に更新される在庫などがある場合、このソリューションは非常に適用しにくいでしょう。 –

+10

ウェブサイトのサイズは、テーブルの数や、エンドユーザーがビアのパラメータでクエリを指示できるものがあることを知ることとはほとんど関係がありません。最終的には、エンドユーザーがこれを最初に行うことを可能にする奇妙なウェブサイトです。 –

-3

結局私は完璧な答えを得ます。 prepare文でテーブル名を動的に書く方法。すべてのトリックは '{}'で起こります。この '{}'の中で変数を使用する必要があります。それは私のコードで動作しています。

+0

これは、「SQLインジェクションから保護するために既存のコンポーネントに追加する」という答えはどうですか? –

関連する問題