web-dev-qa-db-ja.com

これは、SQLクエリへの入力をフィルタリングする安全な方法です。

これは、Java=のSQLクエリに文字列をフィルタリングする安全な方法ですか、それともバイパスできますか?私はすべてをパラメータ化する必要があることを理解していますが、これは、より意味のある古代のコードベースです。自分でやる。

    public static String escapeSQL(String input)
    {
        if (input == null)
            return null;

        return input.replaceAll("'", "\\\\'");
    }
1
Muse4665

これは、安全に近い場所にさえありません。落とし穴はいくつもあります:

  1. Andersが コメント で指摘しているように、\'を挿入することで簡単に回避できます。これは、バックスラッシュをエスケープし、それをリテラルのバックスラッシュに変えて、単一引用符をエスケープしないために機能します。さらに、これは実際に侵入テスト中に試行する非常に一般的なことです。単一引用符をエスケープすることだけが一般的な間違いであるため、これは攻撃者として最初に試みることの1つです。
  2. 文字列のエスケープを処理していますが、整数入力はmore危険です。次のようなクエリの場合:SELECT * FROM table WHERE id=[input]、ユーザー入力は文字列で引用されないため、攻撃者は一重引用符を必要とせずにペイロードを挿入でき、セキュリティを完全に回避できます。もちろん、上記のような条件で使用されるすべての入力が実際には整数であることを確認することでこれを無効にしますが、どこかで忘れた場合はどうなるでしょうか。 ?誰かが句を整数に変更したが、エスケープルールの変更を忘れた場合はどうなりますか?このようなことは常に発生し、安全であったコードが誰にも気付かれずに誤って安全でなくなる可能性が非常に高くなります。それに対する唯一のガードは準備されたクエリです。
  3. マルチバイト文字と文字エンコーディングの違いを適切に説明しましたか?これらの2つのEdgeケースは、あなたがしている単純なエスケープを試みた多くのシステムを噛みました( これはランダムな例です )。

さらにいくつかの落とし穴がありますが、それらは最大のものです。 #1は取引ブレーカーです。選択した実装は安全ではありません。 #2も非常に危険であり、準備済みクエリを使用しない場合、SQLインジェクションの脆弱性が誤って発生することがいかに簡単であるかを強調する必要があります。ですから、率直に言って私を許してしまうとしたら、システムをセキュリティで保護しようとしているのですが、重要で有名な落とし穴を逃してしまいました。つまり、独自のカスタムソリューションを作成する経験がまだない可能性があります。それは本当に大したことではありません-私たちは皆学んでいるので、私たちは皆、いつかこれを理解しなければなりませんでした。それでも、物事を見通しに入れ、2つのオプションのいずれかを提案します。

  1. ややハッキーなソリューションでこれを保護し続けることを続けることができます。これで、これらのことは当初期待していたよりも複雑であることがわかったので、この方法を使用する場合は、SQLインジェクションの脆弱性のリスクが高いことを理解してください。
  2. または、準備されたクエリをそこに取得する方法を理解して、はるかに安全にすることができます。

選択はあなた次第です!

4
Conor Mancone