MySQLデータベースに入力する前に入力をサニタイズするためにPerlで使用できる関数はありますか?正規表現はよくわからないので、自分で関数を作成する前に、すでに正規表現が作成されているのではないかと思っていました。
5 に答える
データベースに挿入するデータをサニタイズする適切な方法は、SQL 文字列に挿入されるすべての変数にプレースホルダーを使用することです。言い換えれば、決してこれをしないでください:
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 ドキュメントを参照してください。
「プレースホルダーを使用する」回答へのマイナーな(そして確かにペダンティックな)補遺:パラメーター化されたクエリは、厳密に言えば「サニタイズ」ではありません。安全にするためにデータを変更することはありません。代わりに、クエリ構造 (コマンド) とデータを別々のチャネルで送信することにより、SQL インジェクションから保護します。
この違いが重要だと思う理由は、データのサニタイズ/引用/エスケープを扱い、パラメータ化されたクエリを使用することは、それらが交換可能であるか、せいぜい、パラメータが危険な文字を引用するためのより良い方法であることを意味するためです。そのプレースホルダーのものをわざわざ理解するのではなく、引用に固執しても大したことはありません。
実際、これらは完全に異なるレベルの信頼性を持つ完全に異なる手法です。引用はインジェクションに対する優れた保護を提供できますが、断固とした攻撃者が引用アルゴリズムを破る、またはすり抜けて、SQL インジェクションを成功させるいくつかのコーナーケースを見つける可能性は常にあります。一方、パラメータ化されたクエリは、 SQL インジェクションに対する完全な保護を提供します。コマンドとデータは別々に送信されるため、データベース エンジンをだましてデータをコマンドとして実行させることはできません。
言語またはデータベース エンジンがクエリでパラメーターを使用できない場合を除き、SQL インジェクションに対する保護としてユーザー入力を引用/エスケープ/サニタイズ しないでください。可能であれば、この目的のために常にパラメータ化されたクエリを使用してください。
また、必須のリンク: http://bobby-tables.com/には、Perl を含むいくつかの異なる言語でパラメーター化されたクエリを使用する方法の例があります。
他の回答で説明されているように、非常にまれなケースでは、プレースホルダーを使用できません。しかし、そのようなまれなケースであっても、潜在的なバグの場所になるため、自分でデータを改ざんするべきではありません。DBIquote
とquote_identifier
メソッドを使用する方がよいでしょう。また、コードが特定の RDBMS にあまり依存しなくなります。
免責事項。以下はダミーの例であり、私が言及した非常にまれなケースを説明するためのものではありません.
$dbh->do('INSERT INTO ' . $dbh->quote_identifier($table) . ' (id, name) VALUES '
'(NULL, ' . $dbh->quote($name) . ')');
データベースをどのように呼び出しますか?
DBIは、プレースホルダーを使用した準備済みステートメントをサポートしています。DBIx::Classと Rose::DB::Objectはどちらも、各ライブラリが提供する「検索」メソッドを使用すると、値を自動的にサニタイズします。