暨『SQL Injection Get Username』這篇以後,同樣也是書上很有趣的手法。
這部份必須要先說明,他是指2的j次方,而非真的有此指令,這需要自己去換算,功用等一下會一併說明。
這段攻擊指令,需要分成幾個階段做說明,首先:
取得字母的ASCII
接下來是
運算邏輯(二進位運算)範例:
範例:
接下來我們就可以開始跑整個流程:
假設current_user()得到的是結果是: root@localhost
接下來就是跑loop,把substring的位置慢慢往後,就可以拼湊出最後的答案。
可能就會有人要問,我要怎樣才能知道已經找到完整的名稱了?
這時候需要用到另外一個函數:
範例:
有人可能會問為什麼要從32開始,因為那是MySQL的Username的長度限制,不過這是針對username的部份,如果針對不同的資料庫,或是欄位這就需要調整,大不了就是從10,000開始總不會錯了吧XD 只是比較浪費時間就是了!
bit-by-bit:逐步推論攻擊
主要需要使用到以下幾個功能:- IF
- ASCII
- SUBSTRING
- 二進制運算
攻擊範例:
上面這是此攻擊的基本公式,當然不是絕對的,另外針對
這部份必須要先說明,他是指2的j次方,而非真的有此指令,這需要自己去換算,功用等一下會一併說明。
這段攻擊指令,需要分成幾個階段做說明,首先:
if(...,1,0)if判斷,true回傳1,否則回傳0
ASCII(...)
取得字母的ASCII
SUBSTRING(... , i , 1)取得字串的第i位起算,1個字母,以 hello 為例:
substring('hello', 1,1) => h substring('hello', 2,1) => o substring('hello', 3,1) => l substring('hello', 3,2) => ll substring('hello', 3,3) => llo
接下來是
&這是mysql裡面的二進制運算符號,
運算邏輯(二進位運算)範例:
1&1 => 1 0&0 => 0 1&0 => 0 0&1 => 0
範例:
5&2^0 => 101 & 001 => 001 5&2^1 => 101 & 010 => 000 5&2^2 => 101 & 100 => 100依照上面的範例,我們可以在不知道5的狀況下,透過運算,逐步推出每一位的結果,進而推論出5這個答案,這是這個攻擊很關鍵的地方!!
接下來我們就可以開始跑整個流程:
假設current_user()得到的是結果是: root@localhost
1. substring("root@localhost",1,1) => r 2. ascii('r') => 114 3. 114&2^j <= 這邊就可以藉由前面所介紹的方式,找出114這個數字
接下來就是跑loop,把substring的位置慢慢往後,就可以拼湊出最後的答案。
可能就會有人要問,我要怎樣才能知道已經找到完整的名稱了?
這時候需要用到另外一個函數:
length()先得到這個名稱的長度以後,再來做拆解的動作。
範例:
if(length(...) < L ,1 ,0 )這裡L是我們要逐步設定的變數,也就是可能長度,我們以上面的例子為例:
if(length('root@localhost') < 32 ,1 ,0 ) => 1 if(length('root@localhost') < 16 ,1 ,0 ) => 1 if(length('root@localhost') < 8 ,1 ,0 ) => 0 if(length('root@localhost') < 12 ,1 ,0 ) => 0 if(length('root@localhost') = 15 ,1 ,0 ) => 0 if(length('root@localhost') = 14 ,1 ,0 ) => 1 (Answer)透過二分法的方式,從很大的數字可以很快的收斂,並且找到確切的字串長度!
有人可能會問為什麼要從32開始,因為那是MySQL的Username的長度限制,不過這是針對username的部份,如果針對不同的資料庫,或是欄位這就需要調整,大不了就是從10,000開始總不會錯了吧XD 只是比較浪費時間就是了!
參考資料:
- http://dev.mysql.com/doc/refman/5.7/en/user-names.html
- https://zh.wikipedia.org/zh-tw/ASCII
- https://en.wikipedia.org/wiki/Bitwise_operation
留言
張貼留言