質問

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

ここに例を示します。名前、住所、電話という列を持つテーブルがあるとします。私が実行しているWebページがあります 列を表示 そして、それらをオプションとして選択ドロップダウンに入力します。

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

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

result = pquery('SELECT * FROM contacts WHERE `' + escape(column) + '`=?', search);

嫌な予感はするけどね。パラメータ化されたクエリを使用している理由は、 逃げる. 。また、 逃げる 列名をエスケープするように設計されていない可能性があります。

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

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

役に立ちましたか?

解決

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

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

run_sql($query, $search);

他のヒント

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

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

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

独自の列名についての推測に頼る必要があります。

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

幸運を祈ります

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

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

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

表示されている大文字が使用されている SomeTable というテーブル (名前の大文字と小文字が変換されたバージョンではありません) から選択され、表示されている大文字が使用されている SomeColumn という列に条件が適用されます。

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

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

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

一部のデータベースでは列名にスペースが含まれる場合があるため、列名を引用符で囲む必要がありますが、データベースにそのような列が含まれていない場合は、SQL に結合する前に正規表現または何らかのチェックを通じて列名を実行するだけです。

if ( $column !~ /^\w+$/ ) {
  die "Bad column name [$column]";
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top