簡體   English   中英

預備語句對SQL注入的影響

[英]Prepared Statement effect against SQL Injection

例如,我有以下代碼:

import java.sql.*; ...
public void main (string[] args){ 
try {
 Class.forName („COM.ibm.db2.jdbc.net.DB2Driver“);} catch (ClassNotFoundException e) {//error handling}
try {
    String url = "jdbc:db2://host:6789/myDB2"
    Connection con = DriverManager.getConnection(url, "login", "password");
    PreparedStatement pStmt = con.prepareStatement("UPDATE PERS SET Salary=Salary*2.0 WHERE PNR=?"

    pStmt.setInt (1, 35);
    pStmt.executeUpdate();

    pStmt.setString (1, args[0]); 
    pStmt.executeUpdate();

    con.close();
    } catch (SQLException e) { //error handling}
}

大概我們有這樣的表:

+--------+----------+-----------+
|PNR     |Name      |Salary     |
+--------+----------+-----------+
|34      |Tim       |20000      |
+--------+----------+-----------+
|35      |John      |45000      |
+--------+----------+-----------+

我很難預測在以下情況下會發生什么情況:

args[0]="35 OR Salary<100000" 

setString命令不是用35 OR Salary < 100000代替args[0] ,然后所有薪水記錄都翻倍了嗎?

那不會導致SQL注入問題。 它將轉換為:

UPDATE PERS SET Salary=Salary*2.0 WHERE PNR='35 OR Salary<100000'

插入的引號將使您免於SQL注入。 我在簡化一點。 JDBC實現確定PreparedStatement轉換為實際SQL查詢的精確程度。 它不一定實際將其轉換為上述SQL。 但這是它可以防止攻擊的一種方法。

不過要小心。 如果使用用戶輸入來創建SQL,則仍然容易受到SQL注入的影響。 只要您僅使用用戶輸入來調用.setXYZ()參數,就可以放心使用。

服務器端預備語句

SQL參數有助於避免SQL注入,因為該參數的值根本沒有與SQL查詢結合。 帶有參數占位符的SQL查詢將發送到MySQL服務器,在此進行解析和分析。 它執行的操作類似於檢查您是否編寫了有效的SQL語法,所引用的表和列是否存在以及是否具有訪問這些表和列的正確權限。

這就是為什么參數不能用於表名或列名或其他語法的原因。 因為驗證是在參數仍保留為占位符時發生的。 參數的值稍后發送,因此驗證必須假定參數必須替換SQL查詢中的單個標量值。

此后,查詢將作為非文本數據結構內部存儲在MySQL服務器中。 它不再在SQL中使用,它只是MySQL代碼中的許多內部對象。 您曾經使用過的地方? 成為MySQL知道可以執行查詢之前需要提供值的查詢元素。

運行pStmt.executeUpdate() ,綁定到參數的變量的值將發送到MySQL服務器。 它們以查詢的非文本表示形式填充到占位符中。

這樣,直到解析完成后,才將參數值組合在一起,因此,參數內容無法更改SQL語法。 它只會像單個字符串那樣影響SQL查詢,就好像存在一種引號定界符,該類型不能用參數內容中不匹配的引號字符來破壞。

查詢參數是防止SQL注入的可靠方法。

模擬准備語句

一些驅動程序執行“模擬”准備好的語句。 這意味着除了將SQL字符串保存在JDBC驅動程序中(在客戶端上prepareStatement()之外,它不會對傳遞給prepareStatement()的SQL查詢執行任何操作。 它此時不將SQL查詢發送到服務器。

然后,當您運行executeUpdate()時, executeUpdate()變量插入到SQL字符串中的參數占位符中,並將完整的字符串發送到服務器。 然后,MySQL服務器使用參數值和全部解析組合的SQL查詢。 MySQL Server甚至無法分辨出哪些值是原始SQL查詢中的文字值,以及哪些組合為參數。 它們全都顯示為解析器的文字值。

在這種情況下,您必須相信JDBC驅動程序可以正確地進行轉義,因此參數內容中的引號和其他字符不會混淆SQL解析器。 應該對驅動程序進行充分的測試,以處理所有情況,例如特殊字符集和十六進制編碼的引號字符以及其他欺騙方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM