如何防御Java中的SQL注入

SQL注入是應(yīng)用程序遭受的最常見的攻擊類型之一。鑒于其常見性及潛在的破壞性,需要在了解原理的基礎(chǔ)上探討如何保護(hù)應(yīng)用程序免受其害。

什么是SQL注入

?SQL注入(也稱為SQLi)是指攻擊者成功篡改Web應(yīng)用輸入,并在該應(yīng)用上執(zhí)行任意SQL查詢。此種攻擊通常會利用編程語言用來括住字符串的轉(zhuǎn)義字符。攻擊者想方設(shè)法用表單字段或URL參數(shù)向應(yīng)用注入額外的SQL代碼進(jìn)而獲得在目標(biāo)數(shù)據(jù)庫上執(zhí)行未經(jīng)授權(quán)的操作的能力。


? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖1:SQL注入原理

SQL注入的影響

實(shí)現(xiàn)SQL注入的攻擊者可以更改目標(biāo)數(shù)據(jù)庫中的數(shù)據(jù)。如果目標(biāo)應(yīng)用使用的數(shù)據(jù)庫連接字符串授予用戶寫入權(quán)限,SQL注入可能會造成重大破壞:攻擊者可以刪除大量數(shù)據(jù),甚至刪除表本身。

此外,即使攻擊者只能獲得對數(shù)據(jù)庫的讀取權(quán)限,也可能會導(dǎo)致敏感數(shù)據(jù)泄露,如財(cái)務(wù)信息或行業(yè)機(jī)密等業(yè)務(wù)敏感信息,以及客戶的私人信息等。隨著隱私法規(guī)越來越完善,數(shù)據(jù)泄露也是SQL注入最危險(xiǎn)的后果之一。

Java中的SQL注入

Java語言已經(jīng)存在了幾十年。盡管開發(fā)人員擁有包含穩(wěn)定的應(yīng)用框架和可靠的ORM的豐富生態(tài)系統(tǒng),仍不足以保護(hù)Java免于SQL注入攻擊。以Ruby為例。盡管Rails是一個穩(wěn)定的開發(fā)框架,但是SQL注入仍構(gòu)成了Ruby應(yīng)用70%的安全威脅。

以如下Java代碼片段為例:

String?sql?=?"select?"

??????+?"id,?title,?excerpt,?body"

??????+?"from?Posts?where?slug?=?'"

??????+?slug?

??????+?"'";

代碼通過關(guān)聯(lián)用戶以某種方式輸入的值(可能是URL參數(shù))來組裝SQL查詢。

這段代碼的問題在于通過用戶提供的值進(jìn)行關(guān)聯(lián)。假設(shè)這個Web應(yīng)用的基URL是

https://example.com/posts

如果我們將my-first-java-project添加到URL中,它變?yōu)?/p>

example.com/posts/my-first-java-projec

相應(yīng)的SQL代碼會變?yōu)?/p>

selectid, title, excerpt,bodyfromPostswhereslug ='my-first-java-project'

這段代碼看起來似乎沒什么問題。

進(jìn)一步地,假設(shè)一個不太善意的用戶將URL設(shè)置為

https://example.com/posts/whatever%27%20or%20%271%27=%271

其中實(shí)際傳遞的參數(shù)是

‘whatever’or‘1’=’1′

得出的SQL代碼是

selectid, title, excerpt,bodyfromPostswhereslug ='whatever'or'1'='1'

現(xiàn)在攻擊者已經(jīng)成功注入了未經(jīng)授權(quán)的代碼。SQL查詢的where子句有了一個判斷' 1 '是否等于' 1 '的附加條件。鑒于1=1是真命題,所有POST請求都可以被取回。

這看起來不是什么大問題;但如果對象是敏感的客戶信息,也即獲取敏感信息只需要一點(diǎn)點(diǎn)SQL注入,問題就不容忽視了。

防御Java?SQL注入的技術(shù)

盡管SQL注入攻擊很常見,而且具有潛在的破壞性,但它們并非無法防御。被利用的漏洞大多源于編碼錯誤,改進(jìn)方向有以下幾種:。

1.使用參數(shù)化查詢

針對Java中的SQL注入,可以從使用參數(shù)化查詢?nèi)胧?。下面的例子基于前一?jié)中提到的查詢語句進(jìn)行了改動

String sql = "selectid, title, excerpt,bodyfromPostswhereslug = ?";

用一個問號形式的占位符替換了關(guān)聯(lián)信息。下一步是創(chuàng)建一個預(yù)編譯語句,并給它綁定參數(shù)值

Connectionconnection = dataSource.getConnection();PreparedStatementp = c.prepareStatement(sql);p.setString(1,slug);

通過使用參數(shù)化查詢,我們可以以一種安全的方式組裝查詢語句與用戶提交的值。

2.允許列表輸入驗(yàn)證

這種方法是使用參數(shù)化查詢的補(bǔ)充。

白名單輸入驗(yàn)證是指將輸入限制為預(yù)先編譯的已知有效值列表,并對其余輸入進(jìn)行攔截。這包括使用正則表達(dá)式來驗(yàn)證某些類型的信息、驗(yàn)證數(shù)值參數(shù)是否符合預(yù)期范圍以及檢查參數(shù)是否符合預(yù)期數(shù)據(jù)類型。

建議對所有類型的用戶輸入進(jìn)行URL參數(shù)、表單字段、導(dǎo)入文件的內(nèi)容等驗(yàn)證。

3.以最小授權(quán)執(zhí)行查詢

SQL注入一旦成功,需確保應(yīng)用使用的連接字符串給予用戶最小授權(quán)。在應(yīng)用的特定部分,唯一需要的數(shù)據(jù)庫權(quán)限是讀取權(quán)限。這里推薦使用只有讀取權(quán)限的連接字符串;即便攻擊者能夠注入未經(jīng)授權(quán)的代碼,至少無法更改或刪除數(shù)據(jù)。

4.利用Java持久化

防御SQL注入的另一種方法是使用JPQL (Java持久性查詢語言)。JPA (Java Persistence API)有幾種實(shí)現(xiàn)方式,最流行的是Spring Data JPA和Hibernate。它們?yōu)閼?yīng)用提供了額外的數(shù)據(jù)層,有助于降低SQL注入成功的概率。

Java安全漏洞概述

SQL注入是Web應(yīng)用最常遭受攻擊類型之一;此外,還有許多安全威脅是Java開發(fā)人員應(yīng)該注意的,包括:

(1) 惡意Jar

(2) XSS注入

(3) Java?LDAP注入

(4) XPath注入

(5) SecurityManager漏洞

以下是一些增強(qiáng)Java應(yīng)用安全性的建議:

1、識別第三方漏洞。現(xiàn)代應(yīng)用通常對第三方庫和工具有很多依賴。使用SCA(軟件成分分析)工具對代碼進(jìn)行檢測,并形成軟件物料清單(SBOM),盤點(diǎn)代碼中引入的第三方組件及這些組件引入的漏洞風(fēng)險(xiǎn),并圍繞SBOM建立安全管理流程。


? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖2:SCA圖例

2、安全左移。在SDLC中盡早引入安全管理,使用自動化工具及相應(yīng)的管理流程來支持安全編碼實(shí)踐。

3、敏捷右移。應(yīng)用上線后進(jìn)入安全運(yùn)營階段,使用監(jiān)控和保護(hù)應(yīng)用安全的工具是關(guān)鍵,RASP能結(jié)合應(yīng)用的邏輯及上下文,以函數(shù)級的精度對訪問應(yīng)用系統(tǒng)的每一段代碼進(jìn)行檢測,實(shí)時監(jiān)控安全狀況、記錄并阻斷攻擊,而無需人工干預(yù)。


? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖3:RASP原理

SQL注入并不復(fù)雜,但其影響卻不容小覷。本文介紹了一些防御手段,以避免Java應(yīng)用成為SQL注入的犧牲品。安全理念、自動化工具及有效的安全管理流程共同構(gòu)成了保護(hù)應(yīng)用免于安全威脅的終極保障。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容