私の職場では、クエリ文字列に安全でないパラメータを連結して 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 です。