4

私は PostgreSQL と通信する比較的小さなアプリケーションを開発していますが、SQL インジェクションに対する保護に関しては、どこまで行き過ぎているかについてフィードバックを得たいと考えていました。

アプリケーションは Perl であり、ORM モジュール (DBI のみ) を使用しません。SQL ステートメントは、プレースホルダーを使用して一般的な方法で構築されます。

my $sql = "SELECT * FROM $cfg->{tablename} WHERE foo = ?";
my $sth = $dbh->prepare($sql);
$sth->execute('bar');

テーブル名が補間される理由は、アプリケーションが複数のテーブルに対して同じ操作を実行する必要があるためです。これらのテーブルにはすべて「foo」列があります。

? の使用 placeholder は、ほとんどの単純な SQL インジェクション攻撃から保護します。私の質問は、プレースホルダーを使用できないテーブル名に関するものです。テーブルは構成ファイルから取得されますが、アプリは代替構成ファイルを使用する --configfile スイッチをサポートしています。

データベース資格情報は構成ファイルに保存されます。そのため、攻撃者が $cfg->{tablename} を悪意のあるものに置き換えた構成ファイルを作成する (または既定のファイルを置き換える) ことができる場合、アプリケーションは「だまされて」悪意のあるコードを実行される可能性があります。

攻撃者がこれを行うには、有効なデータベース資格情報を既に持っている必要があります。そうでない場合、アプリケーションは接続できません。資格情報を持っている場合、DBI を使用して独自のコードを作成するか、psql cli を使用して悪意のあることを行うことができます。

これを防ぐには、次の 2 つの方法が考えられます。

  • ORM に切り替えます。この場合、$orm->get_class_for_table($cfg->{tablename} の順序で何かを行うことになります。
  • SQLステートメントを準備する前に、正規表現を使用してテーブル名をサニタイズします
  • $dbh->quote_identifier() を使用

明らかに 2 番目の方法は「安くて楽しい」方法です。しかし、上記の資格情報に関する声明を考えると、これらのアプローチのいずれかが本当に正当化されるのでしょうか? 攻撃者に別の攻撃ベクトルを使用するように強制することになると、どのくらいの労力がかかりすぎますか (実際に攻撃を防ぐ努力とは対照的に?)

4

2 に答える 2

10

quote_identifierを使用します。

my $sql = "SELECT * FROM ".
  $dbh->quote_identifier($cfg->{tablename}).
  " WHERE foo = ?";
于 2009-07-03T08:50:33.040 に答える
1

このような場合、私は独自のバージョンのプレースホルダーを作成し、テーブル名として挿入する値をチェックして、それが期待するテーブル名であることを確認します。これは、テーブルが存在することを確認するだけではありません。一部の操作は特定のテーブルにのみ影響し、他のテーブルには影響しません。

名前をサニタイズするために正規表現を使用することはありません。彼らはそれを正しく理解し、それがあなたの許可された名前のリストにあるか、彼らがそれを間違ってあなたが彼らにエラーを与えるかのどちらかです。

于 2009-08-07T02:53:57.803 に答える