1. ホーム
  2. データベース
  3. エムエスエル

SQLインジェクションとその防止、マイベイトの基本的な役割について

2022-01-05 04:59:44

SQLインジェクション

SQLインジェクションとは、SQLの構文を利用して、文字列に悪意のあるコードを追加し、不正なデータを取得することです。
例えば、あるユーザーがログインした場合(ユーザー名はadmin、パスワードは123456とする)、通常、次のような文が判断材料になります。

select * from user where username='admin' and password='123456'


レコードが検索された場合はログインが許可され、そうでない場合は "ユーザー名が存在しないか、パスワードが正しくありません" と表示されます。ユーザーのパスワードがわからない、ユーザー名は"admin"であることがわかっている、ユーザー名を入力すると、ユーザー名をadmin'--に変更する、と追加すると、sql文は、次のようになります。

select * from user where username='admin'-- and password='123456'


すると、ログインに成功する。パスワードは以下のようにランダムに入力され、SQLインジェクションを防ぐために何もしなければ、ログインは完全に成功します。

としたらどうでしょう。ユーザー名に "admin; drop table user; -" と入力したら、どうなりますか?

SQLインジェクションを防止する方法

JDBCはSQLインジェクションを防ぐためにPreparedStatementを提供しています。PreparedStatementがSQLをプリコンパイルした後、SQL文のパラメータを代わりに?に置き換えることが必要です。その後、setXX()メソッドを呼び出して、sql文のパラメータを設定します。このようにすれば、特殊な値を渡しても、SQLインジェクションの問題は発生しません。

String sql="select * from user where username='? "+" and password='? ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"admin");
pstmt.setString(2,"123456");
//5. Execute the statement
ResultSet rs=pstmt.executeQuery(sql);


ストアドプロシージャにSQL文を記述し、ストアドプロシージャを介してクエリを完成させる方法もあり、この場合もSQLインジェクションを防止することができます。

マイベットでの${}と#{}の使用について

また、ユーザ名がadmin、パラメータ変数がsnameのような変数の場合は、引用符で囲みません。

select * from user where username='${sname}'
-- In this case, the SQL statement that the high-level language gives to the database is
select * from user where username='admin'


この場合、SQLインジェクションを防ぐ方法はありません。

#はプレースホルダーです。データベース管理システムでのみ "#{}" を使用し、#{} 内のパラメータを

select * from user where username=#{sname}
-- In this case, the SQL is first pre-compiled as follows, and then the parameters are brought in, with single quotes around the values
select * from user where username=?


このケースはSQLインジェクションに対して保護されています

もし#{}がSQLインジェクションを防ぎ、"$ {}"が防げないなら、なぜmybaitsはそのようなシンボルを提供するのでしょうか?SQL文中のデータベースオブジェクトをパラメータとして渡す必要がある場合、** ${}**を使うmyBatisなりの理由があることは確かです。例えば、userテーブル(user)にパラメータ変数tableName='user'を指定して問い合わせる場合、コードは以下のようにしかなりません。

select * from ${tableName}
// Convert to SQL as
select * from user


myBatisでは変数はwhere句のパラメータとして使用され、すべて#{}を使用し、"の使用を禁止する;"SQLインジェクションを防ぐために、データベースオブジェクト(テーブル、ビューなど)を含むSQLステートメントは"のみ使用できます;{} " SQL注入を防ぐために、データベースオブジェクト(テーブル、ビューなど)を含むSQLステートメントは。 SQLインジェクションを防ぐために、""の前にSQL文は、データベースオブジェクト(テーブル、ビューなど)が含まれています"{}"が使用できるため、#{}、自動的に上記の例のように、変数にクォートを入れてください。

select * from #{tableName}
// Convert to SQL statement as
select * from 'user'


<リンク