ユーザーの入力から部分的に形成されたSQLクエリを安全に実行する上での初心者ガイドを教えてください。私はJavaを使用していますが、言語中立ガイドも問題ありません。Javaでのデータベース入力のサニタイズ方法は?
希望の動作は
very nice;) DROP TABLE FOO;
のようなGUIの何かに誰かの種類は、データベースがリテラル文字列として扱い、任意のテーブルを落とすことなく安全に保管するかどうかということです。代わりにStatement
ユーザーの入力から部分的に形成されたSQLクエリを安全に実行する上での初心者ガイドを教えてください。私はJavaを使用していますが、言語中立ガイドも問題ありません。Javaでのデータベース入力のサニタイズ方法は?
希望の動作は
very nice;) DROP TABLE FOO;
のようなGUIの何かに誰かの種類は、データベースがリテラル文字列として扱い、任意のテーブルを落とすことなく安全に保管するかどうかということです。代わりにStatement
間違いなくPreparedStatementを使用します。彼らは便利です。ここにはexampleがあります。
使用PreparedStatementは、あなたが入力を連結し、代わりにPreparedStatementを使用してクエリを作成しないでください。
これにより、クエリ内でパラメータを設定する場所を指定できるため、Javaはすべての入力をサニタイズします。
通常の
PreparedStatement?そのとおり。しかし、もう一つのステップがあると思います。UIからの入力の検証と、データベースに近づく前のオブジェクトへのバインディングです。
私はPreparedStatementの中の文字列は依然としてSQLインジェクション攻撃に対して脆弱あなたを残しかもしれない結合が確認できます。これはリモートである場合
String userInput = "Bob; DELETE FROM FOO";
String query = "SELECT * FROM FOO WHERE NAME = ?";
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, userInput);
ps.executeQuery();
私は、私はそれを自分自身を試していないことを認める奨めしましたが、 PreparedStatementは必要だが十分ではないと言えるだろう。サーバー側の検証とバインドが重要です。
私は、SpringのバインディングAPIを使用して実行することをお勧めします。
あなたのユーザ入力が実際に"Bob'; delete from foo; select '"
(またはそのような何か)でなければならないので、プリペアドステートメントで追加された暗黙の引用符が閉じられることになります。
SELECT * FROM FOO WHERE NAME = 'Bob'; delete from foo; select ''
いますが、準備されたステートメントのコードを引用することを行った場合あなたの引用はあなたが
SELECT * FROM FOO WHERE NAME = 'Bob''; delete from foo; select '''
の実際のクエリを取得し、あなたの名前は"Bob', delete from foo; select '"
の代わりに、複数のクエリを実行しているとして格納されます。
これは、準備文が守るための攻撃のようなものです。それは、エスケープするでしょう。 – danieltalsky
技術的には、PreparedStatementインターフェースはそれを保証しません。あなたのドライバーが何か違うことをしても、新しいベンダーを見つけてください。 –
@ダニエル - 私はそれを試してみる必要があります。私が正しいかどうかにかかわらず、サーバー側の検証はまだまだ良いアイデアだということに同意しないのですか? – duffymo