4

ユビキタスなログイン ハンドラーを含む Linux ベースの perl Web アプリケーションをレビューしています。

my $sth = $DB->prepare("SELECT password from password where userid='$userid'") または die; $sth->実行するか死ぬ; ...

ここで、$userid は (安全でない、フィルター処理されていない) Web ユーザー入力から初期化されます。

DBI ドキュメントでは、このコードをプレースホルダ「?」を使用するように変更することを推奨していることはよく知られています。セキュリティのために「$userid」の代わりに。

このコードは、セキュリティ レビューの目的で、オフ ネットワーク ボックスにそのまま分離されました。 現在、この脆弱性をスキャンするボットが存在するため、インターネット サーバー上のこのようなコードは最終的にクラックされます。また、既知のインジェクションによってデータベースが削除されたり、不正なデータや新しいユーザーが挿入されたり、アクセス制御をバイパスして Web アプリケーションへのエントリが許可されたりする可能性があるため、アクセス制御は重要なものを保護するには効果的ではありません。

アプリケーションは PostgreSQL または MySQL のいずれかを使用するように構成でき、相対的な脆弱性について疑問が生じたため、両方のデータベースを試し、SQL インジェクションを試行して各構成をテストしました。

PostgreSQL では '; を入力します。ここで悪いことをします。そしてここ; 予想どおりログイン cgi をクラッシュさせ、悪いものを実行します。

予想外だったのは、MySQL がこの攻撃に抵抗したことです。これは、DBD::MySQL などに何らかの設定があり、準備を呼び出しごとに 1 つのステートメントに制限したのか、それとも他の方法で MySQL に耐性があるのか​​疑問に思いました。

私が理解しているように、MySQL は一般的に SQL インジェクション耐性がありません。

これは、SQL インジェクションを排除するためのテクニックだけの問題ではありません。そのためには、SQL インジェクション攻撃を回避するにはどうすればよいですか? を参照してください。.

問題は、MySQL は PostgreSQL よりも PERL DBI の下での SQL インジェクション攻撃に対して何らかの形で耐性があるのでしょうか? また、なぜそうなのかということです。

4

4 に答える 4

12

インジェクション攻撃に対する防御は、データベースの責任ではなく、開発者の責任です。開発者がユーザー入力から派生した文字列を連結してクエリを作成するコードを作成すると、結果のクエリはインジェクション攻撃に対して脆弱になり、サニタイズなどに費やされるすべてのコードは時間の無駄です。パラメーター化されたクエリを使用するようにコードが記述されていて、ユーザー入力がパラメーター値として使用されるようになっている場合、結果のクエリはインジェクション攻撃からかなり安全になります。(そして、パラメータ値を介してインジェクション攻撃を行う方法を知りたいです)。

共有してお楽しみください。

于 2010-02-08T17:43:17.997 に答える
8

MySQL クライアント ライブラリは、デフォルトで呼び出しごとに 1 つのステートメントに制限されているようです (PHP で遭遇しました)。

ただし、サブクエリを使用して注入できるため、PostgreSQL ではなく MySQL を使用する理由にはなりません。

于 2010-02-08T13:29:01.857 に答える
3

いいえ、実際には、MySQL はほとんど安全性が低くなります。この場合、prepare ステートメントがサーバー上でまったく実行されていないように見えます。

プリペアド ステートメントのサポート (サーバー側のプリペア) 3.0002_1 の時点で、サーバー側のプリペア ステートメントはデフォルトでオンになっていました (サーバーが >= 4.1.3 の場合)。3.0009 の時点で、準備済みステートメント API の問題により、デフォルトで再びオフになりました (C API の問題が解決されるまで、他のすべての mysql コネクタはこのように設定されます)。サーバー '>= 4.1.3' を使用する準備済みステートメントを使用する要件は引き続き残っています。

サーバー側の準備済みステートメントを使用するには、接続で変数 mysql_server_prepare を設定するだけです。

$dbh = DBI->connect( "DBI:mysql:database=test;host=localhost;mysql_server_prepare=1", "", "", { RaiseError => 1, AutoCommit => 1 } );

  • 注: このパラメーターの区切り文字は「;」です。

サーバー側の準備ステートメントを使用することには多くの利点があります。主に、単一のステートメントが複数の挿入値を受け入れるように準備されているため、多くの挿入を実行している場合です。

「make test」ステップでサーバーの準備が機能するかどうかをテストするには、env 変数 MYSQL_SERVER_PREPARE をエクスポートする必要があります。

エクスポート MYSQL_SERVER_PREPARE=1

おそらく、それらはPostgreSQLのサーバー上に用意されています。

セキュリティに関する限り、あなたは単に間違ってい?ます。あなたが言ったように使用してください。それ以外の場合は、Postgres が複数のステートメントを準備できることを悪用しているだけです。これは否定的なことではありません。MySQLもおそらくこれを行うことができると思います.ここでの唯一の違いはDBDです::MySQLは、C APIの問題がサーバー側の準備の使用を妨げていると主張しているため、サーバーに対して信頼できるものとして他のソースに依存しています. 現在、DBD::MySQL はおそらく mysql ライブラリで C 関数を使用しており、これは MySQL がサーバー側で準備するよりも前のものです (4.1.3 以前は私の推測です)。

于 2010-02-08T18:25:27.810 に答える
0

SQL インジェクションに対する一般的なサニタイザーを用意することは、不可能ではないにしても難しいかもしれません。

[コメントされているように、DBI を正しく使用し、DB のクライアント ライブラリの助けを借りて、SQL ステートメントの準備に関してインジェクションを確実に最小限に抑えることができます。ただし、ユーザー入力のサニタイズには、使用される DB に依存しないアプリケーション ロジックも含まれることに留意することが重要です。たとえば、別のユーザーの資格情報を使用すると、有効で安全なステートメントが提供される場合がありますが、意図しない結果が生じることがあります。とにかく、それは尋ねられた質問よりもさらに進んでいます。]

削除 [これらのタイプの攻撃に対するクライアントの耐性について誤った安心感を抱くよりも、自分で入力をサニタイズしたほうがよいでしょう。それらを使用してはいけないというわけではありませんが、攻撃に対する最小限の助け以上のものを提供するとは思わないでください。]

于 2010-02-08T13:47:42.097 に答える