SQL注入漏洞及綁定變量淺談
1、一個問題引發的思考
大家在群里討論了一個問題,奉文帥之命寫篇作文,且看:
String sql = "update user set user_web="+user_web+" where userid=2343";
大家看看這條sql有沒有問題,會將user_web字段 更新成什么?
問題的結論是:執行后的記錄結果跟執行前一樣,(執行時的sql語句為
user_web字段值被update為自己原有的值),這與作者的本意想違背卻很難被發現有問題。原來的語句漏掉了一對單引號,正確的寫法應該是:
用這種寫法將變量值傳遞到sql語句中,意圖是達到了,但不是好的方式,理由如下:
1.可讀性差。單引號雙引號混雜(試想有多個變量的情況,再想下如果稍一不慎在前面的單引號雙引號直間多個空格又會怎樣?)
2.會造成潛在的性能問題和sql注入漏洞(對測試代碼而言,這兩點可能要求不高,但養成良好的編碼習慣還是很重要的)
下面以非專業人員的角度大致分析下 ‘”+變量+”‘(未采用綁定變量方式)這種方式組織sql為什么會造成潛在的性能問題和sql注入漏洞問題
2、性能問題
Sql代碼不采用綁定變量的方式可能會造成性能問題,表現在以下兩個方面:
1.導致相同的測試計劃被重復執行
sql語句的執行過程分幾個步驟:語法檢查、分析、執行、返回結果。當一條sql通過語法檢查后,會在共享池里尋找是否有跟其相同的語句,如果有則用已有的執行計劃執行sql語句,如果沒有找到,則生成執行計劃,然后才執行sql語句。可見,后者比前者多了額外的步驟,消耗了額外的CPU,并導致sql總體執行時間延長,而這里的關鍵就是“共享池中是否有相同的sql語句”。
String sql = "SELECT id,nick FROM user WHERE username='"+username+"'";
以這樣的方式傳遞到數據庫中的sql為
假定這個語句是第一次執行,會生成執行計劃。當變量發生變化時(username=”test_yy”),數據庫又接收到這樣的語句
Oracle不認為以上兩條語句是相同的,因此又會生成執行計劃,而這兩者的執行計劃是一樣的(做了重復的工作)
2.導致共享池中的sql語句過多,加速SQL老化,造成共享池內部結構頻繁維護。
如果一個某段程序未采用綁定變量的方式而又被大量調用,會導致共享池中不同的sql語句增多,而重用性極低,導致共享池內命中率下降。隨著sql數量過多,一些語句逐漸老化,最終被清理出共享池。 而維護共享池內部結構要消耗大量的CPU和內存資源。
3、Sql注入漏洞
不采用綁定變量的方式可能會造成sql注入漏洞,本文僅僅通過示例說明為什么會造成sql注入漏洞,不對攻擊方式、攻擊類型等展開。以一個用戶驗證為例。
以上代碼接收從客戶端傳來的username和password變量,在數據庫中查詢驗證。假設攻擊者從客戶端傳的username為任意值(如test)password變量為
1′ or ‘1′=’1
此時替換變量后的sql變為
這樣得到的結果就是user表中的所有數據了。
4、使用綁定變量
以上兩種問題的解決方式就是使用綁定變量,就是在sql語句里不直接寫變量,而是用占位符,在執行時再把占位符替換為具體的變量值。代碼片段如下
preparedStatement.setString(1,username);
preparedStatement.setString(2,password);
一些常用Jdbc工具對此進行了良好的封裝,使代碼更加簡潔。比如Spring的SimpleJdbcTemplate
jdbcTemplate.queryForList(sql,username,password);
上面 ?的做占位符的形式被稱為順序占位符,在傳參數值時必須注意順序對應,還有一種是名稱占位符。同樣以SimpleJdbcTemplate為例說明.
map.put("pass",password);
map.put("name",username);
jdbcTemplate.queryForList(sql,map);
上面的例子中的:name和:pass就是名稱占位符,在執行時sql時再綁定變量。
iBatis中有兩種占位符,#name# 和$name$兩種方式,需要注意的是前者會在執行sql時綁定變量,而后者直接是替換為變量值,所以后者仍然存在sql注入漏洞問題。
5、未盡話題
接口測試要不要檢查sql注入漏洞問題?這個問題值得商榷,個人認為通過常規的用例設計檢查sql注入漏洞恐怕不太可行(工作量太大效果不一定好),如果要做的話可借助(或自己開發)一些工具,通過掃描靜態代碼再人工排查的方式進行。另外如果這項工作進行的太細致,恐怕會跟安全測試的工作重疊太多,當然如果在測試過程中發現開發的代碼存在sql注入漏洞(這往往跟開發者編碼習慣有關)問題,一定不要放過,進行排查還是很有必要的。
留言列表