SQL注入
注入攻擊漏洞砖织,例如SQL藏斩,OS以及LDAP注入。這些攻擊發(fā)生在當(dāng)不可信的數(shù)據(jù)作為命令或者查詢語句的一部分劫狠,被發(fā)送給解釋器的時候。攻擊者發(fā)送的惡意數(shù)據(jù)可以欺騙解釋器永部,以執(zhí)行計劃外的命令或者在未被恰當(dāng)授權(quán)時訪問數(shù)據(jù)独泞。
SQL注入.png
我是否存在注入漏洞?
- 檢測應(yīng)用程序是否存在注入漏洞的最好辦法就是確認(rèn)所有解釋器的使用都明確地將不可信數(shù)據(jù)從命令語句或查詢語句中區(qū)分出來。如果可能的話苔埋,在許多情況下懦砂,建議避免解釋器,或禁用它(如组橄,XXE)荞膘。對于SQL調(diào)用,這就意味著在所有準(zhǔn)備語句(prepared statements)和存儲過程(stored procedures)中使用綁定變量(bind variables)玉工,并避免使用動態(tài)查詢語句羽资。
- 檢查應(yīng)用程序是否安全使用解釋器的最快最有效的方法是代碼審查。代碼分析工具能幫助安全分析者找到使用解釋器的代碼并追蹤應(yīng)用的數(shù)據(jù)流遵班。滲透測試者通過創(chuàng)建攻擊的方法來確認(rèn)這些漏洞削罩。
可以執(zhí)行應(yīng)用程序的自動動態(tài)掃描器能夠提供一些信息,幫助確認(rèn)一些可利用的注入漏洞是否存在费奸。然而弥激,掃描器并非總能達(dá)到解釋器,所以不容易檢測到一個攻擊是否成功愿阐。不恰當(dāng)?shù)腻e誤處理使得注入漏洞更容易被發(fā)現(xiàn)微服。
攻擊案例場景
- 場景#1:應(yīng)用程序在下面存在漏洞的SQL語句的構(gòu)造中使用不可信數(shù)據(jù):
String query = "SELECT * FROM accounts WHEREcustID='" + request.getParameter("id") +"'"; - 場景#2:同樣的,框架應(yīng)用的盲目信任缨历,仍然可能導(dǎo)致查詢語句的漏洞以蕴。(例如:Hibernate查詢語言(HQL)):
Query HQLQuery= session.createQuery(“FROM accounts
WHERE custID='“ + request.getParameter("id") + "'");
在這兩個案例中糙麦,攻擊者在瀏覽器中將“id”參數(shù)的值修改成’ or’1’=’1。如:
http://example.com/app/accountView?id=' or '1'='1
這樣查詢語句的意義就變成了從accounts表中返回所有的記錄丛肮。更危險的攻擊可能導(dǎo)致數(shù)據(jù)被篡改甚至是存儲過程被調(diào)用赡磅。
如何防止注入漏洞?
防止注入漏洞需要將不可信數(shù)據(jù)從命令及查詢中區(qū)分開。
- 參數(shù)化語句:使用占位符或綁定常量來向SQL查詢提供參數(shù)宝与,可避免或解決很多在應(yīng)用中經(jīng)常見到的SQL注入問題焚廊,還有擁有相比現(xiàn)代數(shù)據(jù)庫效率更高的優(yōu)勢(數(shù)據(jù)可以根據(jù)提供的預(yù)處理語句來優(yōu)化查詢,從而提高后續(xù)查詢的性能)习劫。
- 輸入驗證:測試應(yīng)用接受的輸入以保證其符合應(yīng)用中定義標(biāo)準(zhǔn)的過程咆瘟。可以簡單到將參數(shù)限制成某種類型诽里,也可以復(fù)雜到使用正則表達(dá)式或業(yè)務(wù)邏輯來驗證輸入
- 白名單驗證(包含驗證或者正驗證): 數(shù)據(jù)類型袒餐、 數(shù)據(jù)大小、 數(shù)據(jù)范圍谤狡、 數(shù)據(jù)內(nèi)容
- 黑名單:常用方法為正則表達(dá)式(推薦使用白名單)
- 編碼輸出:對在應(yīng)用的不同模塊或部分間傳遞的內(nèi)容進(jìn)行編碼(根據(jù)不同的數(shù)據(jù)編碼進(jìn)行替換后傳輸)
- 規(guī)范化:將輸入簡化成便準(zhǔn)簡單的形式(通常最容易實現(xiàn)的一種方法是拒絕所有不符合規(guī)范格式的輸入)
- 通過設(shè)計來避免SQL注入的危險:
- 使用存儲過程:可以防止或減輕SQL注入影響的設(shè)計技術(shù)(幾乎可以杜絕SQL注入)灸眼;
存儲過程非常有助于減輕潛在SQL注入漏洞的嚴(yán)重影響,因為大多數(shù)數(shù)據(jù)庫中使用存儲過程時可以在數(shù)據(jù)庫層配置訪問控制墓懂;發(fā)現(xiàn)SQL注入時幢炸,可以通過正確的配置來保證攻擊者無法訪問數(shù)據(jù)的敏感信息。- 使用抽象層:常見做法是為表示拒贱、業(yè)務(wù)邏輯宛徊、和數(shù)據(jù)訪問定義不同的層,從而將每一層的實現(xiàn)從總體設(shè)計中抽象出來逻澳。
處理敏感數(shù)據(jù):考慮數(shù)據(jù)庫中敏感信息的存儲和訪問
- 口令:存儲每個用戶的口令的salted單向哈希而不是口令本身闸天,將salt(一種附加的少量隨機(jī)數(shù)數(shù)據(jù))與哈希口令分開保存斜做;登錄時不用比較用戶口令和數(shù)據(jù)庫保存的口令苞氮,而是通過用戶提供的信息計算出salted哈希與數(shù)據(jù)庫中保存的哈希值進(jìn)行比較(如果用戶忘記了口令,則生成一個新的口令給用戶)瓤逼。
- 信用卡及其他財務(wù)信息:使用認(rèn)可的(FIPS認(rèn)證過)加密算法來對信用卡等信息進(jìn)行加密笼吟,存儲加密后的明細(xì)數(shù)據(jù)。
- 存檔:考慮每隔一段合理的時間就存檔或清除這些不需要的信息霸旗。
- 避免明顯的對象名:為關(guān)鍵對象(加密函數(shù)贷帮、口令、信用卡列)選取名稱是需要格外小心诱告,eg:password
- 創(chuàng)建數(shù)據(jù)庫honeypot:有人在嘗試從數(shù)據(jù)庫中讀取口令時接收警告撵枢,則可以創(chuàng)建一種帶password(包含假數(shù)據(jù))的附加honeypot(蜜罐),如果假數(shù)據(jù)被選中,那么發(fā)送郵件給應(yīng)用管理員锄禽。
- 附加安全的開發(fā)資源:借助資源向開發(fā)人員提供工具潜必、資源、培訓(xùn)和知識沃但,提高安全性磁滚。
- 平臺層防御:
- 使用運(yùn)行時保護(hù)(成本):檢測、減輕或防止那些不需要重編譯易受攻擊的應(yīng)用的源碼宵晚,即可部署的SQL注入垂攘。
- Web應(yīng)用防火墻:(WAF:網(wǎng)絡(luò)設(shè)備或?qū)踩约拥絎eb應(yīng)用中的一種解決方案)
- 截斷過濾器:在請求資源的核心處理之前或之后執(zhí)行處理操作。
- 不可編輯的輸入保護(hù)和可編輯的輸入保護(hù)
- URL策略/頁面層策略
頁面覆寫:創(chuàng)建一個在運(yùn)行時接受的替代頁面或類
URL重寫:接收那些發(fā)送給易受攻擊頁面或URL請求坝疼,并將他們重定向該頁面的替代版本- 資源代理/封裝
- 面向方面編程
- 應(yīng)用入侵檢測系統(tǒng)
- 數(shù)據(jù)庫防火墻
- 確保數(shù)據(jù)庫安全
- 使用較低權(quán)限的數(shù)據(jù)庫登錄
- 撤銷PUBLIC許可
- 使用存儲過程
- 使用強(qiáng)大的加密技術(shù)來保護(hù)存儲的敏感數(shù)據(jù)
- 維護(hù)一個審查跟蹤
- 確保數(shù)據(jù)庫安全
- 額外的系統(tǒng)對象鎖定
- 約束即席查詢
- 增強(qiáng)對驗證周邊的控制
- 在最低權(quán)限的操作系統(tǒng)賬戶語境中運(yùn)行
- 確保數(shù)據(jù)庫服務(wù)器打了補(bǔ)丁
- 額外的部署考慮
- 最小化不必要信息泄露
- 隱藏錯誤信息
- 使用空的默認(rèn)Web站點(diǎn)
- 為DNS反向查詢使用虛擬主機(jī)名稱
- 使用通配符SSL證書
- 限制通過搜索引擎hacking得到的發(fā)現(xiàn)
- 禁止WSDL信息
- 提高Web服務(wù)器日志的冗余
- 在獨(dú)立主機(jī)上部署Web服務(wù)器和數(shù)據(jù)庫服務(wù)器
- 配置網(wǎng)絡(luò)訪問控制
防止LDAP注入
Function LDAPRequest(id)
LDAPRequest = checkLDAP(Request(id))
end function
'防止LDAP的注入
Function checkLDAP(strHTML)
If Isnull(strHTML) Then
checkLDAP = ""
Exit Function
End If
strHTML=server.HTMLEncode(strHTML)
Dim objRegExp,strOutput
Set objRegExp=New Regexp
objRegExp.IgnoreCase=true
objRegExp.Global=True
objRegExp.Pattern = Chr(0)
strOutput = objRegExp.Replace(strHTML, "")
objRegExp.Pattern = """"
strOutput = objRegExp.Replace(strOutput, """)
objRegExp.Pattern = "\\"
strOutput = objRegExp.Replace(strOutput, "\5c")
objRegExp.Pattern = "NUL"
strOutput = objRegExp.Replace(strOutput, "\0")
objRegExp.Pattern = "/"
strOutput = objRegExp.Replace(strOutput, "\2f")
objRegExp.Pattern = "\*"
strOutput = objRegExp.Replace(strOutput, "\2a")
objRegExp.Pattern = "\("
strOutput = objRegExp.Replace(strOutput, "\28")
objRegExp.Pattern = "\)"
strOutput = objRegExp.Replace(strOutput, "\29")
Set objRegExp=Nothing
checkLDAP = strOutput
end function