[java] PreparedStatementはSQLインジェクションを回避または防止する方法は?



Answers

同じことをする2つの方法を考えてみましょう。

PreparedStatement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();

または

PreparedStatement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();

「ユーザー」がユーザー入力から来て、ユーザー入力が

Robert'); DROP TABLE students; --

それから、最初に、ホースを締めます。 第二に、あなたは安全でリトル・ボビー・テーブルがあなたの学校に登録されます。

Question

私はPreparedStatementsがSQLインジェクションを回避/防止することを知っています。 それはどうですか? PreparedStatementsを使用して構築された最終的なフォームクエリは文字列かそれ以外のものになりますか?




SQLインジェクション:ユーザーがSQL文の一部である可能性のあるものを入力する可能性があるとき

例えば:

文字列クエリ= "INSERT INTO students VALUES( '" + user + "')"

ユーザ入力「Robert」); DROP TABLEの学生; - "を入力として、SQLインジェクションを引き起こす

準備された声明がこれを防ぐ方法は?

String query = "INSERT INTO students VALUES( '" + ":名前" + "')"

parameters.addValue( "name"、user);

=>ユーザーが再び "Robert"を入力したとき); DROP TABLEの学生; - "の場合、入力文字列はドライバ上でリテラル値としてプリコンパイルされ、次のようにキャストされます。

CAST( 'Robert'); DROP TABLEの学生; - 'AS varchar(30))

だから、最後に文字列は文字通りテーブルの名前として挿入されます。

http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection/




準備されたステートメントはより安全です。 パラメータを指定された型に変換します。

たとえば、 stmt.setString(1, user); userパラメータをStringに変換しuser

パラメータに実行可能なコマンドを含むSQL文字列が含まれているとします 。プリペアドステートメントを使用すると、それを許可しません。

これは、メタキャラクター(別名自動変換)を追加します。

これにより、より安全になります。




PreparedStatementで使用されるSQLは、ドライバでプリコンパイルされます。 その時点から、パラメータはSQLの実行可能部分ではなくリテラル値としてドライバに送信されます。 したがって、パラメータを使用してSQLを注入することはできません。 ドライバがSQLの解析とコンパイルをそれぞれ行う必要がないため、PreparedStatementsの別の有益な副作用(プリコンパイル+パラメータのみの送信)は、パラメータに異なる値を指定してもステートメントを複数回実行するとパフォーマンスが向上しますパラメータが変化する時間。




Related