web-dev-qa-db-ja.com

JavaプログラムでのSQLインジェクション攻撃を防ぐ

データベーステーブルを更新するには、Javaプログラムにステートメントを追加する必要があります:

String insert =
    "INSERT INTO customer(name,address,email) VALUES('" + name + "','" + addre + "','" + email + "');";

これは、次のようなSQLインジェクションを通じて悪用される可能性があると聞きました。

DROP TABLE customer; 

私のプログラムにはJava GUIがあり、すべての名前、アドレス、および電子メールの値はJtextfieldsから取得されます。次のコード(DROP TABLE customer;)は、ハッカーによって挿入ステートメントに追加される可能性があり、これを防ぐ方法を教えてください。

12
Grant

PreparedStatement を使用する必要があります。例えば.

String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStatement ps = connection.prepareStatement(insert);
ps.setString(1, name);
ps.setString(2, addre);
ps.setString(3, email);

ResultSet rs = ps.executeQuery();

これにより、インジェクション攻撃が防止されます。

ハッカーがそれをそこに置く方法は、挿入している文字列がどこかの入力から来ている場合です-例: Webページの入力フィールド、またはアプリケーションなどのフォームの入力フィールド。

21
Matt Fellows

この種のコード( "DROP TABLE customer;")をハッカーが挿入ステートメントに追加する方法を知りたいです。

例えば:

name = "'); DROP TABLE customer; --"

この値は挿入になります:

INSERT INTO customer(name,address,email)     VALUES(''); DROP TABLE customer; --"','"+addre+"','"+email+"');

これを防ぐ方法を特に知りたい

プリペアドステートメントとSQL引数を使用します(Matt Fellowsから「盗まれた」例):

String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStament ps = connection.prepareStatment(insert);

また、そのような変数にある値を解析し、許可されていない文字(名前に「;」など)が含まれていないことを確認します。

13
m0skit0

[〜#〜] this [〜#〜] の記事でその情報を確認できます! :)

パラメータ化されたクエリをお勧めします:

String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
7
aF.

攻撃者はemailのフィールドに'[email protected]"); DROP TABLE customer;のようなものを入力するだけで完了です。

JDBCステートメントに適切なエスケープを使用することで、これを防ぐことができます。

5
user647772

そのため、文字列ステートメントで疑問符を使用する必要があります。

 PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                                     SET SALARY = ? WHERE ID = ?");
   pstmt.setBigDecimal(1, 153833.00)
   pstmt.setInt(2, 110592)

ここ から引用

2
dimitrisli

PreparedStatementの利点:PreparedStatementをご覧ください。

SQLステートメントの事前コンパイルとDB側のキャッシュにより、実行が全体的に高速になり、同じSQLステートメントをバッチで再利用できるようになります。

引用符やその他の特殊文字の組み込みエスケープによるSQLインジェクション攻撃の自動防止。これには、PreparedStatement setXxx()メソッドのいずれかを使用して値を設定する必要があることに注意してください

1
Mukesh Kumar

この投稿 で説明されているように、文字列をまだ連結している場合は、PreparedStatementだけでは役に立ちません。

たとえば、1人の不正な攻撃者は引き続き次のことを行うことができます。

  • スリープ関数を呼び出して、すべてのデータベース接続がビジーになるようにします。これにより、アプリケーションが使用できなくなります。
  • dBから機密データを抽出する
  • ユーザー認証をバイパスする

また、SQLだけでなく、バ​​インドパラメータを使用していない場合、JPQLとHQLが危険にさらされる可能性があります。

PreparedStatement ps = connection.prepareStatement(
    INSERT INTO customer(name,address,email) VALUES(?, ?, ?)
);
int index = 0;
ps.setString(++index, name);
ps.setString(++index, address);
ps.setString(++index, email);

ResultSet rs = ps.executeQuery();

結論として、SQLステートメントを作成するときに文字列の連結を使用しないでください。その目的のために専用のAPIを使用します。

1
Vlad Mihalcea

他のすべての回答は、JavaでSQLインジェクションを修正する方法を示していますが、Mukesh Kumarによる回答は、実際には、この種の攻撃を実際に防止しているのは誰かを示しています。 SQLインジェクション攻撃を防止している実際のDBサーバーが、プログラマーとしてparametrizedクエリの使用に関する推奨事項に従っていることを理解してください。

ここを参照-SQLインジェクションの脆弱性の防止

Javaプログラマーがすべての入力文字列をサニタイズすることは不可能であるため、DBベンダーはプリペアドステートメントのオプションを提供し、それを使用してクエリを準備および実行するように指示します。物事はDBベンダーによって処理されます。

DROP TABLE customer;のような劇的なことは起こらないかもしれませんが、SQLインジェクションの基本的な前提は、無効な入力(意図的または非意図的)を提供するだけでクエリを破ることができないということです。

OWASP-SQLインジェクション防止に関するチートシート

0
Sabir Khan

また、データベースにアクセスするアカウントの特権を可能な限り厳しく制限する必要があります。たとえば、検索の場合、アカウントは必要なテーブルと列への読み取りアクセス権のみを持っている必要があります。これにより、SQLインジェクションの損傷を防ぎ、機密データへのアクセスを制限します。

0
Jason210