ibatis執行like查詢時要注意注入漏洞(轉別人的)

看《ibatis in action》,裏面提到了使用like進行模糊查詢的時候,會有注入漏洞。舉例說明如下:

 

<select id="getSchoolByName" resultMap="result">
    select
          *
    from tbl_school
    where school_name like '%$name$%'
</select>
public List<School> getSchoolByName(String name) throws DataAccessException {
	List<School> list = (List<School>)getSqlMapClientTemplate().queryForList("getSchoolByName",name);
	return list;
}

測試用例:

@Test
public void print(){
		try{
			List<School> list = schoolDao.getSchoolByName("長樂一中%' or '1%' = '1");
			for(School school : list){
				System.out.println(school.getName());
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}

用p6spy查看最後生成的sql語句:

 

sql1:select  * from tbl_school where school_name like '%長樂一中%' or '1%' = '1%'   
 
sql2:select  * from tbl_school where school_name like '%長樂一中%' or '1%' = '1%'

其中:sql1是ibatis放入preparedstatement執行的sql,sql2是jdbc執行的真正sql,在這個例子裏二者一樣的,因爲在map裏使用的佔位符是$name$,ibatis遇到這樣的佔位符,就直接拼sql語句了,而不是用在sql中使用佔位符再給sql set paramter(用#name#的話就是,但是不能用來搞模糊查詢)。

 

在實際項目中的後果就是:如果在頁面上有個輸入框,讓用戶輸入學校名字,用戶輸入 長樂一中%' or '1%' = '1 的字樣,那程序就會把所有的學校結果都列出來。實際上可能有一些學校已經被刪除掉了(使用某個字段標記,假刪除),不想讓用戶再看到或者某些學校信息當前用戶沒有權限看到。

 

在《ibatis in action》裏,例舉了這個注入漏洞一個更可怕的後果,刪表。修改測試用例如下:

@Test	
public void print(){
		try{
			List<School> list = schoolDao.getSchoolByName("長樂一中';drop table tbl_test;#");
			for(School school : list){
				System.out.println(school.getName());
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}

用p6spy查看最後生成的sql語句:

select * from tbl_school where school_name like '%長樂一中';drop table tbl_test;#%'
select * from tbl_school where school_name like '%長樂一中';drop table tbl_test;#%' 

在mysql中,#是註釋符.複製以下sql代碼在phpmyadmin中執行,tbl_test確實被刪掉了。但是用ibatis執行這句sql卻失敗,debug了下ibatis的源代碼,發現ibatis是用preparedstatement執行查詢的。上面的是兩個sql語句,但ibatis直接把“select * from tbl_school where school_name like '%長樂一中';drop table tbl_test;#%'”這句sql放進去執行,差不多下面這樣:

String sql = "select * from tbl_school where school_name like '%長樂一中';drop table tbl_test;#%'"
 
PreparedStatement ps = conn.prepareStatement(sql);
 
ps.execute();

這樣的執行就會報錯,也就刪除不了tbl_test這張表了。。。奇怪了。。難道《ibatis in action》這書上講錯了?

以上代碼都是在ibatis2.3.4的環境下測試的。沒試過以前的版本。。

 

但是在使用ibatis的時候難道就不能like查詢了?或者要在web層或者service層對用戶的輸入條件作一次過濾麼?太麻煩了。還好ibatis提供的另一種佔位符#在用PreparedStatement執行查詢的時候,是用?作佔位符,然後set paramter的。。把map裏的sql語句改成這樣吧:(參考了網上的sql語句)

mysql: select * from tbl_school where school_name like concat('%',#name#,'%')
 
oracle: select * from tbl_school where school_name like '%'||#name#||'%'
 
SQL Server:select * from tbl_school where school_name like '%'+#name#+'%'

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章