8

インジェクションを防ぐためにパラメーター化されたクエリを利用するコードがいくつかありますが、テーブルの構造に関係なくクエリを動的に構築できる必要もあります。これを行う適切な方法は何ですか?

以下に例を示します。名前、住所、電話の列を持つテーブルがあるとします。Show Columnsを実行し、選択ドロップダウンにオプションとして入力するWeb ページがあります。

次に、 Searchというテキストボックスがあります。このテキストボックスはパラメータとして使用されます。

現在、私のコードは次のようになっています。

結果 = pquery('SELECT * FROM 連絡先 WHERE `' + エスケープ (列) + '`=?', 検索);

私はそれから不快感を覚えます。パラメータ化されたクエリを使用している理由は、エスケープの使用を避けるためです。また、エスケープは、列名をエスケープするように設計されていない可能性があります。

これが意図したとおりに機能することを確認するにはどうすればよいですか?

編集: 動的クエリが必要な理由は、スキーマがユーザー設定可能であり、ハードコーディングされたものを修正するつもりはないからです。

4

6 に答える 6

6

列名を渡す代わりに、ハードコーディングされたテーブルを使用して列名に変換するコードの識別子を渡すだけです。これは、すべてのデータが合法的に翻訳されているか、無効であることがわかっているため、悪意のあるデータが渡されることを心配する必要がないことを意味します。疑似コード:

@columns = qw/Name Address Telephone/;
if ($columns[$param]) {
  $query = "select * from contacts where $columns[$param] = ?";
} else {
  die "Invalid column!";
}

run_sql($query, $search);
于 2008-09-19T22:03:17.480 に答える
0

秘訣は、ルーチンのエスケープと検証に自信を持つことです。さまざまな型のリテラルに対してオーバーロードされた独自の SQL エスケープ関数を使用しています。ユーザー入力から (引用符で囲まれたリテラル値とは対照的に) 式を直接挿入する場所はどこにもありません。

それでも、それは可能です。列名を検証するための別の (厳密な) 関数をお勧めします。次のような単一の識別子のみを受け入れることを許可します

/^\w[\w\d_]*$/

独自の列名について行うことができる仮定に頼る必要があります。

于 2008-09-19T22:10:51.097 に答える
0

私は ADO.NET を使用し、SQL コマンドと SQLParameters を使用して、エスケープの問題を処理するコマンドを使用しています。したがって、Microsoft ツール環境にもいる場合は、これを使用して動的 SQL を構築し、パラメータを保護することに成功していると言えます。

幸運を祈ります

于 2008-09-19T22:12:46.337 に答える
0

可能なスキーマ値を列挙するテーブルへの別のクエリの結果に基づいて列を作成します。その 2 番目のクエリでは、スキーマの定義に使用される列名に select をハードコーディングできます。行が返されない場合、入力された列は無効です。

于 2008-09-19T22:15:49.900 に答える
0

標準 SQL では、区切り識別子を二重引用符で囲みます。この意味は:

SELECT * FROM "SomeTable" WHERE "SomeColumn" = ?

大文字と小文字が区別された SomeTable というテーブルから選択され (大文字と小文字が変換された名前ではありません)、大文字と小文字が区別された SomeColumn という列に条件が適用されます。

それ自体はあまり役に立ちませんが... Web フォームから入力された名前に二重引用符を使用して escape() 手法を適用できれば、かなり自信を持ってクエリを作成できます。

もちろん、エスケープの使用を避けたいとおっしゃいましたが、実際には、? を提供するパラメーターでそれを使用する必要はありません。プレースホルダー。ただし、ユーザー提供のデータをクエリに入れる場合は、悪意のある人物から身を守る必要があります。

DBMS ごとに、区切り識別子を提供する方法が異なります。たとえば、MS SQL Server は、二重引用符の代わりに角括弧 [SomeTable] を使用しているようです。

于 2008-09-19T22:16:13.380 に答える
0

一部のデータベースの列名にはスペースが含まれている場合があります。つまり、列名を引用符で囲む必要がありますが、データベースにそのような列が含まれていない場合は、SQL にスプライシングする前に、正規表現または何らかのチェックを使用して列名を実行してください。

if ( $column !~ /^\w+$/ ) {
  die "Bad column name [$column]";
}
于 2008-09-19T22:16:26.140 に答える