web-dev-qa-db-ja.com

PerlのDBIを使用してSQLインジェクション攻撃からどのように保護できますか?

MySQLに入力する前に入力をサニタイズするためにPerlで使用できる関数はありますか?私は正規表現をよく知りませんので、自分で関数を作成する前に、すでに作成されているものがあるかどうか疑問に思いました。

40
cskwrd

データベースに挿入するデータを無害化する適切な方法は、SQL文字列に挿入するすべての変数に placeholders を使用することです。つまり、次のことは絶対に行わないでください。

my $sql = "INSERT INTO foo (bar, baz) VALUES ( $bar, $baz )";

代わりに、?プレースホルダー:

my $sql = "INSERT INTO foo (bar, baz) VALUES ( ?, ? )";

次に、クエリを実行するときに置換する変数を渡します。

my $sth = $dbh->prepare( $sql );
$sth->execute( $bar, $baz );

これらの操作をいくつかのDBIコンビニエンスメソッドと組み合わせることができます。上記も書くことができます:

$dbh->do( $sql, undef, $bar, $baz );

詳細については DBI docs を参照してください。

66
friedo

"use placeholders"の解答に対するマイナーな(そして確かに教訓的な)補遺:パラメータ化されたクエリは、厳密に言うと "サニタイズ"ではありません。安全のためにデータを変更することはありません。代わりに、クエリ構造(コマンド)とデータを別々のチャネルで送信することにより、SQLインジェクションから保護します。

この区別が重要であると思う理由は、データのサニタイズ/引用/エスケープとパラメーター化されたクエリの使用を同じものとして扱うことは、それらが交換可能であること、またはせいぜいパラメーターが危険な文字を引用するためのより良い方法であることを意味するためです。プレースホルダーのものを理解するのに煩わされるのではなく、引用に固執するなら大したことではありません。

実際、それらは完全に異なる技術であり、完全に異なるレベルの信頼性を備えています。引用は注入に対して優れた保護を提供できますが、決定的な攻撃者が引用アルゴリズムを破ったり、すり抜けたりするコーナーケースを見つける可能性は常にありますSQLインジェクションを正常に実行できるようにします。一方、パラメータ化されたクエリは、SQLインジェクションに対してabsolute保護を提供します。コマンドとデータは別々に送信されるため、データベースエンジンがデータをコマンドとして実行するようにだまされる可能性はありません

言語またはデータベースエンジンでクエリでパラメーターを使用できない場合を除き、neverquote/escape/sanitize SQLインジェクションに対する保護としてのユーザー入力。 常に可能であれば、この目的のためにパラメーター化されたクエリを使用します。

そして必須のリンク: http://bobby-tables.com/ には、Perlを含むいくつかの異なる言語でパラメーター化されたクエリを使用する方法の例があります。

20
Dave Sherohman

非常にまれなケースでは、他の回答で説明されているように、プレースホルダーを使用できません。ただし、このようなまれなケースであっても、潜在的なバグの原因となるため、自分でデータを改ざんしないでください。 DBIのquoteおよびquote_identifierメソッドを使用することをお勧めします。また、特定のRDBMSに依存するコードが少なくなります。

免責事項以下はダミーの例であり、私が言及した非常にまれなケースを説明するためのものではありません。

$dbh->do('INSERT INTO ' . $dbh->quote_identifier($table) . ' (id, name) VALUES '
    '(NULL, ' . $dbh->quote($name) . ')');
8
codeholic

データベースをどのように呼び出しますか?

[〜#〜] dbi [〜#〜]placeholders を使用した準備済みステートメントをサポートしています。 DBIx :: Class および Rose :: DB :: Object は、各ライブラリが提供する「find」メソッドを使用する場合、値を自動的にサニタイズします。

7
Mikael S

回答:SQLプレースホルダー(?)を使用します。

理由:SQLステートメントの構造とプレースホルダーで表されるデータ値は、完全に別々にデータベースに送信されます。したがって、データ値をSQLコマンドとして解釈できる方法はまったくありません。

0
Yasiru G