web-dev-qa-db-ja.com

一重引用符のフィルタリングはナンセンスですか?

ペネトレーションテスターは、送信されたデータフィールドで一重引用符を使用できることを発見しました。値(値)を許可しないルール(入力検証)を適用することを望んでいます。

SQLインジェクション攻撃では単一引用符が一般的であることは知っていますが、有効な入力として許可されるべきではないことに強く同意します。私は、リモートでSQLフラグメントのように見えるものを除外する代わりに、準備されたステートメント(値を適切に引用する)を使用して、SQLインジェクションを実際に防ぐことを提唱しています。

私の場合:

  • 個人名には一重引用符を含めることができます(O'Reillyなど)
  • テキストフィールドには一重引用符を含めることができます(など)
  • 数値フィールドには単一引用符を含めることができます(EUR 1'000'000
  • などなど

SQLインジェクション防止ルールを適用すると、最も簡単な理由で有効なデータが破棄された(name "Andreas"には[〜#〜]および[〜#〜]、およびプレーンテキストフィールド内のさまざまな一般的な単語は、キーワード「select "、"insert "、"update "または"delete ")。

そのことについてのセキュリティ専門家のスタンスは何ですか?

私が述べた理由により、単一引用符の入力検証の実装を拒否しますか?

237
Peter Walser

入力検証を多層防御メソッドとして実装する必要があります。したがって、入力検証はSQLインジェクションに対する主要な防御であってはならず、準備されたステートメントでなければなりません。追加の防御策として、許可される入力を制限する必要があります。

これによって機能が制限されることはありません。入力にアポストロフィを使用する正当な使用例がある場合は、それを許可する必要があります。したがって、名前フィールド、説明、パスワードでは一重引用符を使用できますが、数値フィールド、ユーザー名フィールド、ナンバープレートフィールドでは使用できません。

すべての入力で単一引用符をブロックすることは狂気です。これはアプリケーションの機能を破壊し、SQLインジェクションに対する正しい解決策にもなりません。

あなたが侵入者の会社を誤解した可能性を考慮してください。これが真剣に彼らのアドバイスである場合、これは侵入テスト会社に悪影響を及ぼします。ソフトウェアを使用不能にするのではなく、ソフトウェアを適切に保護するのに役立つ侵入テストパートナーを探すことをお勧めします。

321
Sjoerd

インジェクション攻撃のコンテキストでは明らかに間違っています。データベースレイヤーが文字列を正しく処理しているか、処理していないかのどちらかです。アポストロフィは名前とフリーテキストで有効であるため、それらを完全にブロックするとアプリケーションが壊れ、選択的にブロックしてもインジェクションの問題は解決しません。

しかし、厳密な入力検証is一般原則の優れた実践であり、過度に寛容であることは、アポストロフィが正当な値の一部ではない場合には意味がありません。ロケール固有の形式(スイスのみ、AFAIK)であるEUR 1'000'000の例を示しますが、その形式を値の一部として許可しても意味がありません。ユーザーが1,500を入力した場合、アプリケーションはそれをそのまま保存する必要がありますか? 1.5と解釈するか1500と解釈するかを処理するたびに決定する必要がありますか?クライアント側でロケール固有の表示を処理し、内部的に正規形式で数値を処理する方が理にかなっています。

したがって、ここでの答えは、監査が意味のある特定のフィールドについて不平を言っているか、アポストロフィの全面禁止を推奨しているかによって異なります。前者の場合、それは正当なポイントです。後者の場合、それらは愚かで、おそらく盲目的にチェックリストに従っています。

27

ステップ1)SQLをパラメーター化します。

ステップ2)SQL DB接続ライブラリを使用してパラメーターの値を設定していることを確認しますnotをインラインで設定するだけです。これは、SQLインジェクションに対する実際の防御策です。

ステップ3)SQLでクエリ構築を行わないでください。その方法は狂気です。

手順4)構成スイッチを追加して、エラーをユーザーに伝達します。テスト中にオンにします。

手順5)ペネトレーションテスターに​​、奇数の単一引用符でSQLエラーを生成する方法を見つけるか、シャットダウンするように伝えます。

17
Joshua

準備されたステートメント(パラメーター化されたクエリ)は、正しく実装することを確認するだけですばらしいです。脆弱性のある「準備済みステートメント」の実装を見てきました。実装の詳細については、スタックオーバーフローをお勧めします。

また、多層防御(この場合は入力検証)に問題はありませんが、うまく実行してください...すべての単一引用符を拒否することは、おそらくベストプラクティスではありません:)

12
DarkMatter

私は警備員ではありません。私は安全なコードを維持しなければならないプログラマーです。これは私が「もろい」慣行と呼んでいるものです。エントリポイントは、一般的なプロジェクト全体に散在しています。それらすべてを見つけてサニタイズすることは、単一の問題のみに対処するための多くの作業であり、多くの注意深いメンテナンスと、コードが変更されても効果を維持するための手間と、それを無効にする仮定に満ちています。

代わりに、保守が容易で、階層化され、状況に応じて、幅広い問題を解決する方法を使用してください。そうすれば、高価で広範にわたるフィルタリングは必要ありません。

それらがどのように使用されるかわからない場合、入力を保護することはできません。

全体のすべての入力からすべての単一引用符を取り除いて、システムを「保護」したとしましょう。 oneタイプのSQLインジェクション攻撃に対して安全です。その入力がaで使用されている場合...

  • 二重引用符を許可するMySQLクエリ
  • ファイルシステム操作
  • シェルコマンド
  • ネットワーククエリ
  • メソッド名
  • クラス名
  • eval

これらにはそれぞれ、異なる特殊文字、エスケープシーケンス、引用ルール、およびセキュリティプラクティスがあります。入力がどのように使用されるかを予測することはできません。すべての特殊文字を取り除こうとすることは狂気であり、1つのクラスの攻撃しか「解決」しません。

または、ユーザーがページ制限を入力できる場合はどうなりますか。この制限は、パラメーター化されたクエリで忠実に使用されます。 SQLインジェクションはありません。ユーザーが9999999999を入力すると、DOS攻撃を受けやすくなります。

安全でない可能性のある操作が実行される時点で、適切なセキュリティ対策を適用する必要があります。これには、操作に固有の多くの要素が考慮されます。入力文字のサニタイズは1つだけです。

そして、そうしている限り、クエリをパラメータ化することもできます。そうすれば、ブランケットストリッピングクォートのすべての作業と損傷を行う必要がなくなります。

すべての入力のフィルタリングは困難です。

特定のプロジェクトで入力を取得して渡す方法はたくさんあります。

  • フォーム入力
  • uRL
  • ファイル名
  • ファイルの内容
  • データベースクエリ
  • ネットワーク読み取り
  • 環境変数

これらは通常かなり自由形式であり、さまざまなライブラリを使用できます。潜在的に脆弱なすべての入力がフィルタリングを通過したことを確認する静的分析ツールについては知りません。一部の言語には taint system がありますが、効果的に使用することは困難です。すべての入力をフィルタリングしても、静的分析ツールがないと、開発が進むにつれてフィルタリングされていない入力がリークして戻ってきます。機能を妨げる結果を維持することは、不完全で費用がかかるために多大な労力を要します。

対照的に、プロジェクトでSQLを実行する方法は通常1つだけです。潜在的なSQLインジェクションを自動的に検出するための静的ツールとランタイムツールが存在します。文字列を完全に禁止し、すべてのクエリをSQLクエリオブジェクトにすることもできます。これらの優れたプラクティスは保守が容易であり、ツールやSQLライブラリにますます組み込まれています。

「ファイアウォール」は緩やかなセキュリティにつながります。

「ファイアウォールがある」ために一部のオフィスネットワークが非常に安全でない慣行を持っているのと同様に、「入力が安全」であるためにチームがコードの保護について怠惰になるリスクがあります。入力は間違いなく安全ではありません。

機会費用

「なぜ両方ではないのか」と言う人もいます。あなたはプロジェクトに取り組むために非常に多くの時間を持っています。効率が低く、保守作業が多いのは時間の無駄です。それを実装して保守することで、限られた時間を、より効率的で保守しやすいプラクティスから遠ざけることができます。最悪の場合、入力を使ったモグラの再生に非常に多くの時間を費やし、あまりにも積極的なフィルタリングが原因で発生するその後の問題により、適切なセキュリティ対策を講じることができません。

要するに、入力フィルタリングは高価で、漏れやすく、保守が難しく、問題を解決できず、さらに悪化させる可能性があります。

11
Schwern

ご自分で言ったように、パラメーター化されたクエリを使用している場合、一重引用符は問題ではありません。この場合、あなたは彼らのアドバイスを拒否することができます。そうする場合は、パラメーター化されたクエリを使用してあるであり、これが(前の例を使用して)使いやすさにも役立つことを強調します。

8
Philip Rowlands

SQLインジェクションをすべての場所で常に防ぐことが100%確実である場合、これは実際にナンセンスです。

ただし、SQLインジェクションは最も一般的なセキュリティリスクの1つであり、パラメーターを使用するようにアプリケーションを適切に作成したと確信していても、ずさんなDBAが 二次SQLのリスクがあるクエリを実行する可能性があります。注入 。それはどこにも保存されていないかもしれません、それは単にテーブルをコピーするためのクエリかもしれません。

2次攻撃は実行が困難ですが、防御は困難です。 2次攻撃からの保護は、信頼されていないソースからの入力を処理するSQLステートメントだけでなく、書き込み権限を持つデータベースで実行されるすべての動的SQLステートメントをSQLインジェクションのリスクについてチェックする必要があることを意味します。

すべての場所で引用を禁止することは、2次攻撃に対するずさんな保護ですが、可能性は低くなります。理想的な世界ではそれは必要ではないでしょうが、残念なことに私たちは1つに住んでいません。

多くのユーザーがデータベースに対する何らかの形式の書き込みアクセス権を持ち、独自のSQLステートメントを書き込むことができる場合、それは賢明なセキュリティ対策になる可能性があります。アプリケーションがデータベースにアクセスする唯一の方法であり、非常に知識のあるユーザーだけが書き込みアクセスで自分のクエリを実行できる場合、通常は必要ありません。

8
Erik A

私はあなたのアプリケーションの詳細を知りませんが、私はあなたの主張に従います。

特定の文字を含める必要がないフィールドがあります。これらのフィールドを使用すると、could入力検証を使用して、単一引用符(および二重引用符など)をフィルタリングします。

エスケープが正しく機能しなかった場合、入力検証は軽減戦略である可能性がありますが、SQLインジェクションのリスクを軽減するには、準備されたステートメントを(正しく)使用することをお勧めします。

6
Tobi Nary

これが本物の侵入テストの結果である場合、彼らはこれが悪用可能な問題であることを証明する提出する価値をあなたに提供できるはずです。彼らができない場合は、適切な侵入テストを依頼することをお勧めします。

ただし、これが一般的な脆弱性スキャンの結果である場合、私はこのようなあいまいな一般的な応答を期待します。これは、単一引用符を挿入できるというフラグを立てるだけです。この場合、問題がないことに満足していれば、その結果を喜んで無視できます。

4
Jason Leaman

これは視点の問題だと思います。あなたのシステムには最初に来るべき機能要件があります。これは、入力検証の問題を検討する価値がないという意味ではありません。ところで、この2つは直接対立するものではありません。これはお勧めしませんが、フロントエンドでエンコードとデコードを行い、SQLストレージとクエリでエンコードされた形式を使用することは可能です。

バランスは主観的であり、言及されていないもののホストに依存します。あなたは彼らに明確にするように頼むかもしれません。彼らには非常に正当な理由があるかもしれませんが、そうではないかもしれません。

1
ANone

元Web開発者で、今はペンテスターですが、ユーザー入力を制限したくないのですが、これは大きな問題になる可能性があります。私はこの手法を使って自分でWebアプリケーションとデータベースを侵害したことを知っています。

私の意見では、エスケープ文字を処理するためにDBインストールとWeb言語(php)構成を確認し、モジュールをコーディングして入力を反復し、適切にフォーマットされていることを確認します。

アポストロフィは有効な入力ですが、渡されるデータベースステートメントをエスケープして攻撃ベクトルを導入することもできます。 DBおよびWeb言語には、これらのタイプのインスタンスを処理できるモジュールがありますが、独自のモジュールを作成して再確認することをお勧めします。

1
MrNiceGuy