【Javaプログラミング】JDBC注入攻撃-SttementとPreparedSttement


前回の「Javaプログラミング」で簡単なJDBC接続-Drivers,Connection,Sttement and PreparedStatimentを紹介しました。JDBCドライバを使って簡単な接続を構築し、StationとPreparedStationを使ってデータベース検索することができます。このブログは引き続きSQLで攻撃比較StationとPredStrementを注入します。もちろんこの2つは他にもいろいろな違いがありますが、これからもブログで更新していきます。
【Sttementクエリ】
1、DBHelper.javaにusernameとpasswordでuserを検索する方法を追加します。
	public static void queryByUser(String username,String password) {
		Connection conn = DBConnection.getConnection();
		Statement stmt = null;
		ResultSet rs = null;
		try {
			stmt = conn.createStatement();
			rs = stmt.executeQuery("select * from user where username = '" + username+"' and password='"+password+"'");
			while (rs.next()) {
				User user = new User();
				user.setId(rs.getInt("id"));
				user.setUsername(rs.getString("username"));
				user.setPassword(rs.getString("password"));
				user.setGender(rs.getBoolean("gender"));
				user.setRegtime(rs.getDate("regtime"));
				System.out.println(user.toString());
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			DBConnection.closeResultSet(rs);
			DBConnection.closeStatement(stmt);
			DBConnection.closeConnection(conn);
		}
	}
2、DBHelper Test.javaにテスト方法を追加してテストする。
	public void queryByUserTest(){
		DBHelper.queryByUser("jack", "jack");
	}
Javaエンドテストの結果:
User[id=2、username=jack、password=jack、gender=true、regtime=2014-05-14]
テスト結果は、有効なユーザ名とパスワードにより、ユーザのすべての情報を取得することに成功したことを示しています。
3、MySQLログ情報を通じて、sql文を追跡します。具体的な方法はMySQLを参照して、sql文を追跡する方法です。
mysql.logログを開いて、追跡して最新のログを調べます。以下の通りです。
140514 10:16:13	   15 Query	SET character_set_results = NULL
		   15 Query	SHOW VARIABLES
		   15 Query	SHOW WARNINGS
		   15 Query	SHOW COLLATION
		   15 Query	SET autocommit=1
		   15 Query	select * from user where username = 'jack' and password='jack'
		   15 Quit	
ログ情報によると、データベース側で正常なクエリ文が実行されています。
4、DBHelperTest.javaに注入攻撃テストを追加し、ユーザー名入力:hack(任意の文字列)、パスワード入力:or'1'='1
	public void queryByUserInjectTest(){
		DBHelper.queryByUser("hack", "' or '1'='1");
	}
Javaエンドテストの結果:
User[id=1、username=andy、password=andy、gender=true、regtime=2014-05-13]
User[id=2、username=jack、password=jack、gender=true、regtime=2014-05-14]
User[id=3、username=rose、password=rose、gender=false、regtime=2014-05-13]
テストの結果は、攻撃を注入することによって、ユーザーがuserテーブル内のすべてのユーザ情報を不正に入手できるということを示しています。
5、MySQLログ情報を通じて、sql文を追跡して調べ、データの端に何があったかを分析する。
140514 10:23:14	   16 Connect	root@localhost on db_bbs
		   16 Query	SET NAMES latin1
		   16 Query	SET character_set_results = NULL
		   16 Query	SHOW VARIABLES
		   16 Query	SHOW WARNINGS
		   16 Query	SHOW COLLATION
		   16 Query	SET autocommit=1
		   16 Query	select * from user where username = 'hack' and password='' or '1'='1'
		   16 Quit	
データベース端でステートメントが実行されました。
select*from user where username='hack'and password=''or'1'='1'
where条件が本物であるため、実行に相当します。
select*from user 
この文ですべてのユーザ情報を取得しました。
【PreparedSttementクエリ】1、DBHelper.javaにusernameとpasswordでuserを検索する方法を追加しました。
public static void queryPrepareByUser(String username,String password) {
		Connection conn = DBConnection.getConnection();
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			ps = conn.prepareStatement("select * from user where username = ? and password = ?");
			ps.setString(1,username);//        
			ps.setString(2, password);
			rs = ps.executeQuery();
			while (rs.next()) {
				User user = new User();
				user.setId(rs.getInt("id"));
				user.setUsername(rs.getString("username"));
				user.setPassword(rs.getString("password"));
				user.setGender(rs.getBoolean("gender"));
				user.setRegtime(rs.getDate("regtime"));
				System.out.println(user.toString());
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBConnection.closeResultSet(rs);
			DBConnection.closeStatement(ps);
			DBConnection.closeConnection(conn);
		}
	}
2、DBHelper Test.javaに試験方法を追加して試験を行う。
public void queryByPreparedUserTest(){
		DBHelper.queryPrepareByUser("jack", "jack");
	}
Javaエンドテストの結果:
User[id=2、username=jack、password=jack、gender=true、regtime=2014-05-14]
テスト結果は、合法的なユーザー名とパスワードによって、このユーザのすべての情報が得られたことを示しています。
3、 MySQLログ情報を通じて、sql文を追跡します。
140514 10:37:04	   17 Connect	root@localhost on db_bbs
		   17 Query	SET NAMES latin1
		   17 Query	SET character_set_results = NULL
		   17 Query	SHOW VARIABLES
		   17 Query	SHOW WARNINGS
		   17 Query	SHOW COLLATION
		   17 Query	SET autocommit=1
		   17 Prepare	select * from user where username = ? and password = ?
		   17 Execute	select * from user where username = 'jack' and password = 'jack'
		   17 Close stmt	
		   17 Quit	
ログ情報によると、まずデータベース端末が実行されました。
プリコンパイルして、通常のクエリ文を実行しました。
4、DBHelper Test.javaに注入攻撃テストを追加しました。
	public void queryByPreparedUserInjectTest(){
		DBHelper.queryPrepareByUser("hack", "' or '1'='1");
	}
Javaエンドテストの結果:
何のメッセージも印刷されていません。つまりユーザの情報が得られませんでした。注入攻撃は無効ですか?
5、MySQLログ情報を通じて、sql文を追跡しますが、なぜ攻撃を注入して無効になりましたか?
140514 10:42:42	   19 Query	SET character_set_results = NULL
		   19 Query	SHOW VARIABLES
		   19 Query	SHOW WARNINGS
		   19 Query	SHOW COLLATION
		   19 Query	SET autocommit=1
		   19 Prepare	select * from user where username = ? and password = ?
		   19 Execute	select * from user where username = 'hack' and password = '\' or \'1\'=\'1'
		   19 Close stmt	
		   19 Quit	
元は実行されました。select*from user where username='hack'and password=''\r\1'=''1'
【参考】
JDBC Steement vs PreparedStation–SQL Injection Example(推奨)
JDBCはなぜプレハブを使ってSttementではないですか?
【興味があるかもしれません】
簡単なJDBC接続-Drivers,Connection,Sttement and PreparedSttementを建立します。
転載は出典を明記してください。http://blog.csdn.net/andie_gro/articale/detail/25775163ありがとうございます。