溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何以Java的視角來進(jìn)行SQL注入

發(fā)布時(shí)間:2021-10-11 10:12:51 來源:億速云 閱讀:284 作者:柒染 欄目:MySQL數(shù)據(jù)庫(kù)

這篇文章給大家介紹如何以Java的視角來進(jìn)行SQL注入,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

前言

靶場(chǎng)準(zhǔn)備

首先我們來準(zhǔn)備一個(gè)web接口服務(wù),該服務(wù)可以提供管理員的信息查詢,這里我們采用springboot + jersey 來構(gòu)建web服務(wù)框架,數(shù)據(jù)庫(kù)則采用最常用的mysql。下面,我們來準(zhǔn)備測(cè)試環(huán)境,首先建立一張用戶表jwtk_admin,SQL如下:

然后插入默認(rèn)的管理員:

這樣我們就有了兩位系統(tǒng)內(nèi)置管理員了,管理員密碼采用MD5進(jìn)行Hash,當(dāng)然這是一個(gè)很簡(jiǎn)單的為了作為研究靶場(chǎng)的表,所以沒有很全的字段。

接下來,我們創(chuàng)建 spring boot + jersey 構(gòu)建的RESTFul web服務(wù),這里我們提供了一個(gè)通過管理員用戶名查詢管理員具體信息的接口,如下:

SQL注入測(cè)試

首先我們以開發(fā)者正向思維向web服務(wù)發(fā)送管理員查詢請(qǐng)求,這里我們用PostMan工具發(fā)送一個(gè)GET請(qǐng)求

不出我們和開發(fā)者所料,Web接口返回了我們想要的結(jié)果,用戶名為admin的管理員信息。OK,現(xiàn)在開發(fā)任務(wù)完成,Git Push,Jira任務(wù)點(diǎn)為待測(cè)試,那么這樣的接口就真的沒有問題了嗎?現(xiàn)在我們發(fā)送這樣一條GET請(qǐng)求:

發(fā)送該請(qǐng)求后,我們發(fā)現(xiàn)PostMan沒有接收到返回結(jié)果,而Web服務(wù)后臺(tái)卻開始拋 MySQLSyntaxErrorException異常了,錯(cuò)誤如下:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘‘xxxx’’’ at line 1

原因是在我們查詢的 xxxx’ 處sql語句語法不正確導(dǎo)致。這里我們先不討論SQL語法問題,我們繼續(xù)實(shí)驗(yàn),再次構(gòu)造一條GET查詢請(qǐng)求:

此時(shí),我們可以驚訝的發(fā)現(xiàn),查詢接口非但沒有報(bào)錯(cuò),反而將我們數(shù)據(jù)庫(kù)jwti_admin表中的所有管理員信息都查詢出來了:

這是什么鬼,難道管理員表中還有 name=xxxx’or’a’=’a 的用戶?這就是 SQL Injection。

注入原理分析

在接口中接受了一個(gè)String類型的name參數(shù),并且通過字符串拼接的方式構(gòu)建了查詢語句。在正常情況下,用戶會(huì)傳入合法的name進(jìn)行查詢,但是黑客卻會(huì)傳入精心構(gòu)造的參數(shù),只要參數(shù)通過字符串拼接后依然是一句合法的SQL查詢,此時(shí)SQL注入就發(fā)生了。正如我們上文輸入的name=xxxx’or’a’=’a與我們接口中的查詢語句進(jìn)行拼接后構(gòu)成如下SQL語句:

當(dāng)接口執(zhí)行此句SQL后,系統(tǒng)后臺(tái)也就相當(dāng)于拱手送給黑客了,黑客一看到管理員密碼這個(gè)hash,都不用去cmd5查了,直接就用123456密碼去登錄你的后臺(tái)系統(tǒng)了。Why?因?yàn)?23456的md5哈希太常見了,別笑,這就是很多中小網(wǎng)站的現(xiàn)實(shí),弱口令橫行,不見棺材不落淚!

好了,現(xiàn)在我們應(yīng)該明白了,SQL Injection原因就是由于傳入的參數(shù)與系統(tǒng)的SQL拼接成了合法的SQL而導(dǎo)致的,而其本質(zhì)還是將用戶輸入的數(shù)據(jù)當(dāng)做了代碼執(zhí)行。在系統(tǒng)中只要有一個(gè)SQL注入點(diǎn)被黑客發(fā)現(xiàn),那么黑客基本上可以執(zhí)行任意想執(zhí)行的SQL語句了,例如添加一個(gè)管理員,查詢所有表,甚至“脫褲” 等等,當(dāng)然本文不是講解SQL注入技巧的文章,這里我們只探討SQL注入發(fā)生的原因與防范方法。

JDBC的預(yù)處理

在上文的接口中,DAO使用了比較基礎(chǔ)的JDBC的方式進(jìn)行數(shù)據(jù)庫(kù)操作,直接使JDBC構(gòu)建DAO在比較老的系統(tǒng)中還是很常見的,但這并不意味著使用JDBC就一定不安全,如果我將傳入的參數(shù) xxxx’or’a’=’a 整體作為參數(shù)進(jìn)行name查詢,那就不會(huì)產(chǎn)生SQL注入。在JDBC中,提供了 PreparedStatement (預(yù)處理執(zhí)行語句)的方式,可以對(duì)SQL語句進(jìn)行查詢參數(shù)化,使用預(yù)處理后的代碼如下:

同樣,我們使用上文的注入方式注入 ,此時(shí)我們發(fā)現(xiàn),SQL注入沒能成功?,F(xiàn)在,我們來打印一下被被預(yù)處理后的SQL,看看有什么變化:

看到了嗎?所有的 ’ 都被 ’ 轉(zhuǎn)義掉了,從而可以確保SQL的查詢參數(shù)就是參數(shù),不會(huì)被惡意執(zhí)行,從而防止了SQL注入。

Mybatis下注入防范

MyBatis 是支持定制化 SQL、存儲(chǔ)過程以及高級(jí)映射的優(yōu)秀的持久層框架, 其幾乎避免了所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。同時(shí),MyBatis 可以對(duì)配置和原生Map使用簡(jiǎn)單的 XML 或注解,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄,因此mybatis現(xiàn)在在市場(chǎng)中采用率也非常高。這里我們定義如下一個(gè)mapper,來實(shí)現(xiàn)通過用戶名查詢管理員的接口:

同樣提供Web訪問接口:

接下來,我們嘗試SQL注入name字段,可以發(fā)現(xiàn)注入并沒有成功,通過打印mybatis的Log可以看到mybatis框架對(duì)參數(shù)進(jìn)行了預(yù)處理處理,從而防止了注入:

那是否只要使用了mybatis就一定可以避免SQL注入的危險(xiǎn)?我們把mapper做如下修改,將參數(shù)#{name}修改為${name},并使用name=‘xxxx’ or ‘a(chǎn)’=‘a(chǎn)’ 作為GET請(qǐng)求的參數(shù),可以發(fā)現(xiàn)SQL注入還是發(fā)生了:

那這是為什么,mybatis ${}與#{}的差別在哪里?

原來在mybatis中如果以形式聲明為SQL傳遞參數(shù),mybatis將不會(huì)進(jìn)行參數(shù)預(yù)處理,會(huì)直接動(dòng)態(tài)拼接SQL語句,此時(shí)就會(huì)存在被注入的風(fēng)險(xiǎn),所以在使用mybatis作為持久框架時(shí)應(yīng)盡量避免采用

形式聲明為SQL傳遞參數(shù),mybatis將不會(huì)進(jìn)行參數(shù)預(yù)處理,會(huì)直接動(dòng)態(tài)拼接SQL語句,此時(shí)就會(huì)存在被注入的風(fēng)險(xiǎn),所以在使用mybatis作為持久框架時(shí)應(yīng)盡量避免采用形式聲明為SQL傳遞參數(shù)。

mybatis將不會(huì)進(jìn)行參數(shù)預(yù)處理,會(huì)直接動(dòng)態(tài)拼接SQL語句,此時(shí)就會(huì)存在被注入的風(fēng)險(xiǎn),所以在使用mybatis作為持久框架時(shí)應(yīng)盡量避免采用{}的形式進(jìn)行參數(shù)傳遞,如果無法避免(有些SQL如like、in、order by等,程序員可能依舊會(huì)選擇${}的方式傳參),那就需要對(duì)傳入?yún)?shù)自行進(jìn)行轉(zhuǎn)義過濾。

JPA注入防范

JPA是Sun公司用來整合ORM技術(shù),實(shí)現(xiàn)天下歸一的ORM標(biāo)準(zhǔn)而定義的Java Persistence API(java持久層API),JPA只是一套接口,目前引入JPA的項(xiàng)目都會(huì)采用Hibernate作為其具體實(shí)現(xiàn),隨著無配置Spring Boot框架的流行,JPA越來越具有作為持久化首選的技術(shù),因?yàn)槠淠茏尦绦騿T寫更少的代碼,就能完成現(xiàn)有的功能。

例如強(qiáng)大的JpaRepository,常規(guī)的SQL查詢只需按照命名規(guī)則定義接口,便可以不寫SQL(JPQL/SQL)就可以實(shí)現(xiàn)數(shù)據(jù)的查詢操作,從SQL注入防范的角度來說,這種將安全責(zé)任拋給框架遠(yuǎn)比依靠程序員自身控制來的保險(xiǎn)。因此如果項(xiàng)目使用JPA作為數(shù)據(jù)訪問層,基本上可以很大程度的消除SQL注入的風(fēng)險(xiǎn)。

但是話不能說的太死,在我見過的一個(gè)Spring Boot項(xiàng)目中,雖然采用了JPA作為持久框架,但是有一位老程序員不熟悉于使用JPQL來構(gòu)建查詢接口,依舊使用字符串拼接的方式來實(shí)現(xiàn)業(yè)務(wù),而為項(xiàng)目安全埋下了隱患。

安全需要一絲不茍,安全是100 - 1 = 0的業(yè)務(wù),即使你防御了99%的攻擊,那還不算勝利,只要有一次被入侵了,那就有可能給公司帶來很嚴(yán)重的后果。

關(guān)于JPA的SQL注入,我們就不詳細(xì)討論了,因?yàn)榭蚣芟碌淖⑷肼┒磳儆诳蚣苈┒捶懂牐ㄈ鏑VE-2016-6652),程序員只要遵循JPA的開發(fā)規(guī)范,就無需擔(dān)心注入問題,框架都為你做好幕后工作了。

SQL注入的其他防范辦法

很多公司都會(huì)存在老系統(tǒng)中有大量SQL注入風(fēng)險(xiǎn)代碼的問題,但是由于其已穩(wěn)定支持公司業(yè)務(wù)很久,不宜采用大面積代碼更新的方式來消除注入隱患,所以需要考慮其采用他方式來防范SQL注入。除了在在SQL執(zhí)行方式上防范SQL注入,很多時(shí)候還可以通過架構(gòu)上,或者通過其他過濾方式來達(dá)到防止SQL注入的效果。

一切輸入都是不安全的:對(duì)于接口的調(diào)用參數(shù),要進(jìn)行格式匹配,例如admin的通過name查詢的接口,與之匹配的Path應(yīng)該使用正則匹配(因?yàn)橛脩裘胁粦?yīng)該存在特殊字符),從而確保傳入?yún)?shù)是程序控制范圍之內(nèi)的參數(shù),即只接受已知的良好輸入值,拒絕不良輸入。注意:驗(yàn)證參數(shù)應(yīng)將它與輸出編碼技術(shù)結(jié)合使用。

利用分層設(shè)計(jì)來避免危險(xiǎn):前端盡量靜態(tài)化,盡量少的暴露可以訪問到DAO層的接口到公網(wǎng)環(huán)境中,如果現(xiàn)有項(xiàng)目,很難修改存在注入的代碼,可以考慮在web服務(wù)之前增加WAF進(jìn)行流量過濾,當(dāng)然代碼上就不給hacker留有攻擊的漏洞才最好的方案。也可以在擁有nginx的架構(gòu)下,采用OpenRestry做流量過濾,將一些特殊字符進(jìn)行轉(zhuǎn)義處理。

盡量使用預(yù)編譯SQL語句:由于動(dòng)態(tài)SQL語句是引發(fā)SQL注入的根源。應(yīng)使用預(yù)編譯語句來組裝SQL查詢。

規(guī)范化:將輸入安裝規(guī)定編碼解碼后再進(jìn)行輸入?yún)?shù)過濾和輸出編碼處理;拒絕一切非規(guī)范格式的編碼。

其實(shí)隨著ORM技術(shù)的發(fā)展,Java web開發(fā)在大趨勢(shì)上已經(jīng)越來越遠(yuǎn)離SQL注入的問題了,而有著Entity Framework框架支持的ASP.NET MVC從來都是高冷范。在現(xiàn)在互聯(lián)網(wǎng)中,使用PHP和Python構(gòu)建的web應(yīng)用是目前SQL注入的重災(zāi)區(qū)。

關(guān)于如何以Java的視角來進(jìn)行SQL注入就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI