Web安全之防止SQL注入


所謂SQL注入式攻擊,就是輸入域或頁面請求的查詢字符串,欺騙服務器執行惡意的SQL命令。在某些表單中,用戶輸入的內容直接用來構造(或者影響)動態SQL命令,或作為存儲過程的輸入參數,這類表單特別容易受到SQL注入式攻擊。

導致原因及可能后果

通過將帶有惡意目的的SQL語句或參數寫入表單中進行提交,程序未經過校驗直接執行SQL語句,導致一些敏感數據泄露包括一些用戶名密碼信息等,以及可能會對數據庫信息進行增刪改操作,篡改數據等嚴重后果。

一些例子

直接動態拼接SQL語句

反例:

String username = request.getParameter("username");
String password = request.getParameter("password");
String encryptedPass = PasswordUtil.encrypt(password);
String sql = "select * from users where username = '" + username + "' and password = '" + encryptedPass + "'";
Statement s = c.createStatement();
ResultSet rs = s.executeQuery(sql);

正例:

String username = request.getParameter("username");
String password = request.getParameter("password");
String encryptedPass = PasswordUtil.encrypt(password);
String sql = "select * from users where "
			+ "username = ? and password = ?";
PreparedStatement s = c.prepareStatement(sql);
s.setString(1, username);
s.setString(2, encryptedPass);
ResultSet rs = s.executeQuery();

如果用戶登錄時候在username和passwor分別填入

username = "‘1' or '1'='1‘";
password = "’1' or '1'='1’";

最終SQL語句就會變成

String sql = "select * from users where "
	+ "username = '1' or '1'='1' and password = '1' or '1'='1'";

由於where條件永為真,那么最后相當於執行

String sql = "select * from users"

直接曝露所有用戶信息。更有甚者,可將語句變為

String sql = "select * from users;drop table users;"

將用戶數據全部刪除。

因此,需要使用PreparedStatement對象而不是用Statement對象來預編譯SQL語句。主要有三點優勢:

  1. PreparedStatement可以寫動態參數化的查詢
  2. PreparedStatement比 Statement 更快
  3. PreparedStatement可以防止SQL注入式攻擊

使用mybatis框架動態參數使用'$'而不是'#'

反例:

<dynamic prepend="where">
<isParameterPresent>
	<isNotEmpty prepend="and" property="onShelves">
		p.onshelves=$onShelves$
	</isNotEmpty>
</isParameterPresent>
</dynamic>

正例:

<dynamic prepend="where">
<isParameterPresent>
	<isNotEmpty prepend="and" property="onShelves">
		p.onshelves=#onShelves#
	</isNotEmpty>
</isParameterPresent>
</dynamic>

'#'解析為一個 JDBC 預編譯語句(prepared statement)的參數標記符。而'$'僅僅為一個純碎的 string 替換,在動態 SQL 解析階段將會進行變量替換。
注意點:

  1. 能使用 #{}的地方就用 #{}
  2. 表名作為變量時,必須使用 ${}

如何防止

  1. 永遠不要信任用戶的輸入。對用戶的輸入進行校驗,可以通過正則表達式,或限制長度;對單引號和雙"-"進行轉換等。
  2. 永遠不要使用動態拼裝sql,可以使用參數化的sql或者直接使用存儲過程進行數據查詢存取。
  3. 可通過一些檢查方法來進行安全測驗。sql注入的檢測方法一般采取輔助軟件或網站平台來檢測,軟件一般采用sql注入檢測工具jsky,網站平台就有億思網站安全平台檢測工具。

參考資料

  1. 利用SQL注入漏洞登錄后台
  2. JDBC為什么要使用PreparedStatement
  3. mybatis之#和$區別


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM