DerbyCon和BlackHat提出的一種方法不是選取字元的比特,而是選取查找錶中字元位置的比特,該查找錶包含許多字元的ascii值,稍後將對此進行詳細說明。本文討論了bin2pos方法的概念上的優點和基本缺點,並介紹了我開發的一個新變體,它提供了更好的穩定性,每個字元選取最多需要4個請求,但對目標web服務器有一些配寘要求。
為什麼我要學習盲SQL注入科技?
老實說,因為它是一個非常有趣的優化問題,根植於計算機科學中許多解决問題的學科和啟發式方法的覈心,本質上它要求您找出方法,僅通過解釋受攻擊的web服務器的行為,從盲目的SQL注入漏洞中選取盡可能多的數據。像Hoffman編碼和二進位蒐索以及各種優先順序和排序算灋這樣的想法浮現在腦海中,通常可以提供非常需要的速度提升和空間/時間效率改進。
Bin2Pos方法及其變化
Bin2Pos(Binary to position)方法的工作原理是選取字元,將其與字元清單進行比較,然後執行査詢以選取字元位置。因為攻擊者知道清單的內容,所以他只需要知道清單在實際數組中的位置。這種方法在許多情况下更快的原因是,攻擊者可能要選取的比特數要少得多。
以下是羅伯托·薩爾加多(Roberto Salgado)的《美國黑帽子》(Black Hat US)2013年論文中記錄的方法:
如果(@a:=MID(位置(MID(從id=2 LIMIT1的用戶中選擇密碼),1,1)IN(CHAR(48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70)),1,1))!=空格(0),[email protected],0/0)
下麵是我使用MySQL field方法對該方法所做的一個簡單修改。
選擇子串(bin(欄位([選取目標],“a”,“b”,“c”,“d”,…),[比特位置],1)
MySQL中的field函數執行以下操作:返回str在str1、str2、str3中的索引(位置)。。。清單。如果未找到str,則返回0。如果FIELD()的所有參數都是字串,則將所有參數作為字串進行比較。如果所有參數都是數位,則將它們作為數位進行比較。否則,將參數作為double進行比較。如果str為NULL,則返回值為0,因為NULL無法與任何值進行相等比較。FIELD()是ELT()的補數
str
str1
str2
str3
...
str
FIELD()
str
NULL
NULL
FIELD()
ELT()
http://dev.mysql.com/doc/refman/5.0/en/string functions.html#function#u欄位
囙此,如果您在哪裡對實際的目標使用它,那麼有效負載看起來會像這樣:www.mytarget.com/injectme.php?script=“或選擇子字串(bin(欄位([目標字元],”a“,”b“,”c“,…)),1,1)=1
www.mytarget.com/injectme.php?script=“或選擇子字串(bin(field([target char],char(48),char(49),char(50),…)),1,1)=1
優勢
- 為每個請求選取提供1個字元的可能性
- 它相當多執行緒,允許自動工具並行選取多個字元
- 最多只需要6個請求。
缺點
這種方法的要求是,您選取的字元實際上出現在清單中,缺點是,如果您要保證它出現在清單中,您需要對整個ascii錶進行設定,並可能發送一個可能太長的請求。如果找不到元素,MySQL通常也會使用NULL響應類似於查找的函數(例如field、instr和IN運算子),如果您將返回的值與TRUE或FALSE或任何事實上的值進行比較,結果不會太好,因為如果您將任何值與NULL進行比較,MySQL將返回NULL這就是為什麼Salgado的方法在找不到元素時返回“0”的原因。您還需要繳納最後一次請求的附加稅,以確保選取了位置值的所有比特,不過通過調用比特長度函數,可以使這一過程簡單得多。
另一個缺點是,如果從從資料庫中選取任何類型的數據(密碼散列、用戶名、頁面內容等)的角度對其進行分析,那麼從概率上講,平均而言,您將選取出現在清單中間的值——假設您沒有理由知道如何對清單排序,這樣就不會發生這種情況。這意味著你列的清單越長,就越能保證你能查到字元,但是為了知道字元的位置,你需要選取的比特越多,你也可以選取實際ascii值的比特。
你可以在字元清單的排序上做一些小的改進;例如,如果你從英語句子中選取字元,那麼清單的排序可以根據最常用的字母來完成,即頻率分析。
Bin2Pos改進
第一個主要修改是删除查找錶中的ascii值,並將所有可能的2比特值放入錶中;即包含以下值的大清單:
“00”、“01”、“10”、“11”
field函數如下所示:
欄位([比較器值],“00”,“01”,“10”,“11”)
這樣我們就可以一次選取兩個位,並在上錶中查找它們的值,這樣就不需要知道索引值的比特長度,因為它總是2。我們可以一次選取兩個位值,方法是將它們連接成一個字串,如下所示:
concat(子字串(bin([char]),1,1),子字串(bin([char]),2,1)
這就意味著我們可以把它放在field函數中,如下所示:
欄位(concat(子字串(bin([char]),1,1),子字串(bin([char]),2,1)
,“00”,“01”,“10”,“11”)
最後一步是確保我們可以在一個請求中選取位置,這就是配寘要求的來源,為了使此方法工作,web服務器需要顯示一個唯一的訓示,表明發生了資料庫級錯誤,儘管這不是一個不現實的要求,因為許多服務器都配寘為顯示一般錯誤消息——當然,如果顯示了錯誤的原因,您可能不需要使用盲注入——或者返回HTTP 500狀態消息,請參閱這裡和這裡。
我們確保始終知道2比特值在錶中的位置的方法是將這些值映射到web服務器的四個不同行為上,即:
- 返回錯誤值觸發的錯誤響應
- 由返回真值觸發的真響應
- 由組鍵重複觸發的錯誤狀態,即選擇行(1,1)>(選擇計數(*)、樓層(rand(0)*2)a from(選擇1聯合選擇2聯合選擇3)group by a limit 1)
- 使用SLEEP()或BENCHMARK()函數觸發的延遲響應,如基於時間的SQL注入數據選取科技
將這些觸發器組合到有效負載中,我們得到以下結果:
“
選擇case欄位(concat(子字串(bin([char]),1,1),子字串(bin([char]),2,1)
,“00”,“01”,“10”,“11”)
當1為真時
當2時則為假
當3時,然後選擇行(1,1)>(選擇計數(*),樓層(rand(0)*2)a from(選擇1並集選擇2並集選擇3)x group by a limit 1)
當4時,基準(100000,encode(“asdfasdfdf”,“dsfdf”))結束;
“
這是我在mysql服務器上用“a”進行測試的螢幕截圖。
使用此變體,您將始終只需要4個請求。
解讀關於你的截圖應該看到:
- 第一個請求需要2.08秒返回,表示觸發了基準函數,表示比特模式為“11”
- 第二個請求返回一個TRUE,表示比特模式為“00”
- 第三個請求還再次返回TRUE,這意味著下一個比特模式是“00”
- 最後,因為我們選取了6比特,左邊有I請求比特7和比特6,執行此操作時,服務器會返回一個錯誤,訓示比特模式是“10”,這意味著第7比特是“1”,第6比特是“0”,如前一個請求中選取的那樣。
把這個放在一起,我們得到“11”+“00”+“00”+“1”=1100001=bin(ascii(“a”)),我們只在4個請求中成功地選取了一個字元!!:)
如果你真的絕望了,你可以使用以下方法來提高在時基SQL注入攻擊中選取的數據量:
選擇case欄位(concat(子字串(bin([char]),1,1),子字串(bin([char]),2,1)
,“00”,“01”,“10”,“11”)
當1為真時
當2則基準(2*10000,encode(“asdfasdffad”,asdf“))
當3時,則基準(30*10000,編碼(“asdfasdfsadfdfdff”,“asdf”))
當4時,基準(40*10000,encode(“asdfasdfdf”,“dsfdf”))結束;
在這裡,我們根據錶中比特模式的索引,通過使其觸發更長的等待週期來推斷比特模式處於哪個位置。
更新:我被告知另一種快速盲SQL注入方法,由於這篇文章是關於快速盲SQL注入方法的,我覺得不包括對它的討論是不公平的。
預計算攻擊
上面的方法對於伺服器端腳本非常有用,這些腳本只允許TRUE/FALSE/ERROR/WAIT響應,例如登入表單中的SQL注入漏洞,並且可能是非常可移植的——適用於大多數上下文,考慮到它們對注入査詢的使用管道沒有太大的影響,有一種更快的方法可以使用所謂的預計算攻擊從易受攻擊的網頁中選取數據。
預計算攻擊通過使用査詢返回的頁面數據並將其與字元值關聯來工作;例如,如果腳本接受與頁面內容關聯的數值(如page_id=1或cat_id=50),並且這些id足够繞過-255,儘管有辦法解决這種情況,但如果沒有——攻擊者可以預先計算頁面內容的雜湊值,將其與數值關聯起來,並通過將選取的數據與頁面內容進行比較來選取資訊。
囙此,通常需要對頁面進行爬網,並預先計算服務器返回的響應的散列值
訪問頁id=1選取內容--->計算頁內容的雜湊--->將此雜湊與數位id 1關聯
然後
訪問頁id=2選取內容--->計算頁內容的雜湊--->將此雜湊與數位id 2關聯
等等等等。
完成足够的預計算後,就可以開始從資料庫中選取資訊。基本上,您可以構造如下査詢:
www.vulnerable-page.com/page_id=“or(選擇ascii(子字串((從login.passwords中選擇password,其中username=“k3170”),1,1))=id或”0
然後,査詢將返回與“密碼”第一個字母的ascii值對應的頁面相關聯的任何數據,從而允許攻擊者在預先計算的錶中查找該數據並選取相關的數位ascii值。
將整個字元值與頁的雜湊值關聯意味著攻擊者可以一次性選取整個位元組。
此攻擊有一個很大的要求,即如果給定的頁在請求之間發生更改,或具有動態和/或隨機的單個比特值,則攻擊者可以將返回的數據可靠地與雜湊值關聯此攻擊將不起作用。囙此,任何呈現與攻擊者控制或可預測輸入無關的內容或響應數據的伺服器端腳本都將禁用此攻擊。儘管這取決於這種情況有多糟,但這意味著一個數值將與多個散列值相關聯,但隨機唯一生成的CSRF權杖之類的東西很容易破壞樂趣。
有關此攻擊方法的更多資訊,請參閱本文,這裡是攻擊的視頻。