0

私の職場では、クエリ文字列に安全でないパラメータを連結して SQL クエリを作成するのが伝統でした。もちろん、これは SQL インジェクションの脆弱性につながります。これが発生するすべての Java ソフトウェアは、すべてのユーザーが信頼されていると想定される閉じたネットワーク上で実行されるため、これは大きな問題とは見なされませんでした。また、クエリはデータベースにアクセスできるクライアント側アプリケーションから実行されるため、技術的にはユーザーが悪意のあるクエリを実行する可能性があります。

それにもかかわらず、データベース層の新しいバージョンで準備済みステートメントをサポートする予定です。それまでの間、既存のデータベース レイヤーの上に小さなライブラリを作成しました (これは、SQL 文字列からのクエリの実行のみをサポートし、準備されたステートメントやパラメーターのエスケープのオプションはありません)。これにより、文字列パラメーターをエスケープすることで安全なパラメーター化クエリを作成できます.

このライブラリの一部として、文字列リテラルをエスケープする次のメソッドを作成しました。PHP の addlashes 関数と同じ文字をエスケープしますが、補助 (32 ビット) 文字を検出することで、マルチバイト文字の脆弱性を回避しようとします。

private String escapeString(String str)
{
    List<Character> toEscape = Arrays.asList('\'', '"', '\\', '\0');

    StringBuilder result = new StringBuilder();
    for(int i = 0; i < str.length(); ++i)
    {
        char c = str.charAt(i);

        if(i < str.length() - 1 && c >= '\uD800' && c <= '\uDBFF')
        {
            char next = str.charAt(i + 1);

            if(next >= '\uDC00' && next <= '\uDFFF')
            {
                // Two-char supplementary character. Escape neither.
                result.append(c);
                result.append(next);
                ++i;
                continue;
            }
        }

        if(toEscape.contains(c))
        {
            // Special character. Add escaping \.
            result.append('\\');
        }

        // Copy character itself.
        result.append(c);
    }

    return result.toString();
}

私の質問は、クエリをエスケープするこの方法が十分に安全かどうかです (そして、私は何も監視していないか、実装ミスを犯していません)。入力文字列は有効な UTF-16 であると想定できます。これが使用される DBMS は、MySQL と Oracle です。

4

2 に答える 2

4

ORM、プリペアド ステートメント、またはストアド プロシージャがなければ、文字列 SQL サニタイズ ルーチンには注意が必要です。

于 2012-05-25T13:29:03.887 に答える
1

いいえ。

PIN を入力する整数フィールドがあるとします。

"SELECT columns FROM table WHERE PIN = " + サニタイズ文字列

次に、入力用に次のように入力します: 1234 OR 1 = 1

そして今、あなたの「ピン」は常に受け入れられ、面白い文字は使用されていません.

これは int 以外のフィールドでも機能する可能性があります (はい、SQL に渡す前に int 入力が実際に int であることを検証できるため)。

于 2012-05-25T15:40:04.697 に答える