access偏移注入原理


  • 前言:近段時間在學習access偏移注入時,在網上查詢了大量的資料,感覺很多資料講解的十分模糊並且我個人認為有很多不夠嚴謹的地方,於是我便在線下經過大量測試,寫出以下文章,如有錯誤,望指出。
  • 如要轉載,請標明出處!!

一、認識偏移注入

  • 偏移注入的適用背景:
    • access數據庫與mysql不同,access數據庫沒有類似於mysql的information_schema這樣的系統數據庫,所以對於access的表名及其字段名我們只能靠經驗進行猜解,而偏移注入就是提供了另外一種思路:
    • 在我們只能猜解出表名,而猜解不出我們所想要的字段名的情況下,直接爆最后的字段數據。
  • 偏移注入的原理(這里只是粗略的概述,詳細請看下面):
    • 就是將目標表進行(多級)內連接,通過聯合查詢和已知目標字段名的微調,將我們想要知道的字段值在已經確定的顯示位上暴露出來。
  • 影響偏移注入成功率的因素(當然這些因素都是影響因素,不是決定因素):
    1. 聯合查詢中顯示位的位置
    2. 當前注入點所查詢的字段數量
    3. 目標表的字段數量
    4. 我們可以猜解到的目標表的字段名的數量

二、實戰測試環境

  • 此次實戰測試主要涉及的兩張表:product表和admin表
    • product表:該表有22個字段
      01_access偏移注入-product表
    • admin表:該表有6個字段(請謹記這個字段數
      02_access偏移注入-admin表

三、前置知識

  1. exist()函數:用於檢查子查詢是否至少會返回一行數據,該子查詢實際上並不返回任何數據,而是返回值True或False。
    03_access偏移注入-exist函數

  2. as關鍵字:用於起別名,可以為表起別名,也可以為字段起別名(as關鍵字可省略)
    04_access偏移注入-as關鍵字

  3. 表1 inner join 表2 on 篩選條件 :該關鍵字用於將表1與表2做笛卡爾積,然后根據on后面的條件進行篩選。

    • 下圖中select語句的意思是:將admin表與自己做笛卡爾積,然后篩選出兩者id值相同的記錄
      05_access偏移注入-內連接
  4. top n 關鍵字:作用是使查詢結果只顯示前n條記錄
    06_access偏移注入-top關鍵字

四、原理講解

  • 為了方便講解,我們在這里選擇 “實戰” 和 “偏移注入的注入原理” 相結合的方式進行討論。
  • 偏移注入的流程是:
    1. 判斷是否存在注入點
    2. 判斷當前注入點所查詢的字段數量 (請一定謹記以下的簡略表述,后面的文章均采用以下簡略表述)
      • 為方便之后講解,我們
      • 把【當前注入點對應表】稱作為 【當前表】
      • 把【當前注入點所查詢的字段數量】稱作為【當前字段數量】
      • 把我們將要進行【聯合查詢的表】稱為【目標表】
      • 使用sql語句幫助理解:select 當前字段數量 from 當前表 union select ... from 目標表
      • 在這里【當前表】->product表;【目標表】->admin表
    3. 猜解目標表的表名
    4. 確定顯示位
    5. 確定目標表的字段數量
    6. 開始進行偏移注入,經過不斷的“微調”,將我們想要的字段值在顯示位處暴露出來。

4.1 判斷是否存在注入點

  • payload:
    • ?id=1513 and 1=2 頁面顯示出錯
    • ?id=1513 and 1=1 頁面顯示正常
    • 說明存在注入點,且為數字型注入
      07_access偏移注入-注入點的判斷

4.2 判斷注入點所查詢的字段數(即:當前字段數量)

  • payload:
    • ?id=1513 order by 22
    • 頁面返回正常,說明當前注入點本身所查詢的字段數量為22(即:當前字段數量為22)
      08_access偏移注入-判斷注入點所查詢的字段數

4.3 猜解目標表的表名

  • payload:
    • ?id=1513 and exists(select * from admin)
    • 因為access數據庫沒有類似於mysql的information_schema這樣的系統索引庫,所以我們只能根據經驗靠猜了,在真實的測試環境中,我們也可以通過社工的方式進行猜解。此次頁面返回正常,說明存在access數據庫中存在admin表。
      09_access偏移注入-猜解目標表的表名

4.4 確定顯示位

  • payload:
    • ?id=1513 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 from admin
    • 在頁面的源碼中,我們可以看到存在3,9,13,15 四個顯示位
      10_access偏移注入-確定顯示位

4.5 確定目標表的字段數量

  • payload:
    • ?id=1513 and exists(select * from admin order by 6)
    • 頁面返回正常,說明admin有6個字段
      11_access偏移注入-確定目標表的字段數

4.6 開始進行偏移注入

  • 偏移注入的基本公式

    • 聯合查詢所要補充的字段數 = 當前字段數量 - 目標表的字段數 x N(N=1,2...)【注意:“聯合查詢所要補充的字段數” 指的是union關鍵字后面的select查詢所需補充的字段數】
    • 在此處即為:聯合查詢補充字段數 = 當前字段數量(22) - admin表的字段數(6) x N
    • 當N=1時我們稱為 “1級偏移注入”,當N=2時我們稱為 “2級偏移注入”;當N=3時我們稱為 “3級偏移注入”,...
  • 1級偏移注入的payload

    • 根據公式我們可以計算出:聯合查詢補充字段數 = 22-6x1 = 16
    • ?id=1513 union select top 1 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, * from admin
    • 在這里我們解釋一下,為什么1級偏移注入並沒有爆出我們想要的字段值呢:
      • 由前面的步驟我們已經得知,已經確定的顯示位只有 3,9,13,15 四個,即只有處於第3,9,13,15這四個字段的數據才可以顯示出來,
      • 但是我們觀察下標發現,在進行1級偏移注入時,admin表的數據實際上是排在了17號字段之后了,當然不會在頁面中顯示出來。
      • 那么我們怎么樣才可以將admin表的數據向前移動,以致可以使其處於第3,9,13,15號字段而顯示出來呢?
      • 答案是:我們可以進行2級(多級)偏移注入(即通過admin表的自連接使得sql語句中“ * ”所代表的的字段數增大,那么聯合查詢中用於充數字段就會減小,這樣的話,admin表中的數據自然會向前移動了)
        12_access偏移注入-1級偏移注入
  • 2級偏移注入的payload

    • 根據公式我們可以計算出:聯合查詢補充字段數 = 22-6x2 = 10
    • ?id=1513 union select 1,2,3,4,5,6,7,8,9,10, * from (admin a inner join admin b on a.id=b.id)
    • 根據頁面返回的數據,我們可以看到,在第13號顯示位,我們成功的爆出了 密碼值:a48e190faf
    • 但這是為什么呢?
      • 通過分析下圖中表2我們發現,經過2級偏移注入,我們成功的將admin表的數據向前移動了6個字段,使其原本在17號字段及其之后才顯現出的數據,變為了在11號字段及其之后就可回顯而出。而此時admin表的password字段和count_time字段恰好處於顯示位13和15上,於是就自然而然的暴露了出來。
    • 那又為什么admin表的數據會向前移動6個字段呢?
      • 原因就是,由於admin表進行了一次自連接,使得payload中from關鍵字后面的表由原有的 “admin表” 變成了:由“先讓admin自己做笛卡爾積然后挑選id值相等的記錄”組成的表。這樣的話,payload中的“ * ”就由原來所代表的 “admin表” 中的6個字段,變為了現在所代表的 “admin自連接表” 的12個字段,又由於union關鍵字的使用,要求union關鍵字后面select查詢的字段數必須要等於前面select查詢的字段數,所以union關鍵字后面的select中用於充數的字段由原來的22-6=16變為了22-12=10個字段,因此由於充數的字段變少了,那么admin表的數據自然的就可以向前移動了。
      • 請注意:admin表中的數據向前移動的字段數只能是admin表(即目標表)字段數的整數倍(這是由表自連接的特性所決定的)。
        13_access偏移注入-2級偏移注入
    • 在此我們已經爆出了admin表的密碼,
    • 此時,其實admin表的admin字段就緊挨在password字段的前方(其實在實戰環境中我們是不確定admin字段是在前還是在后的,此處只是為了方便原理的講解,就直接告訴你了)
    • 那么我們是否仍然可以將數據向前移動而爆出admin字段的值呢?在這里顯然是不行的,因為我們只能向前移動admin表的字段數量的整數倍(在這里即是6的整數倍),而此時admin表的admin字段此時所處字段為12號字段,再向前移動6個字段的話,admin字段就處於6號字段處了,仍然沒有與顯示位的位置發生重合。
  • 到了這里,細心的同學會發現:

    • 之前我們講的都是如何將admin表中的數據向前移動,那么我們可不可以使得數據向后移動呢?要是可以向后移動的話,緊接着2級偏移,然后讓數據向后移動一個字段,不就正好讓admin字段處於13號顯示位了嗎?
    • 恭喜你!你的想法是對的,我們的確可以讓admin表的數據向后移動,不過遺憾的是,向后移動的字段數仍然取決於:我們能夠猜解出admin表中多少個字段名。若猜解出1個字段名,那么我們就可以讓數據向后移動1個字段數,若猜解出2個字段名,那么我們就可以讓數據向后移動2個字段數,以此類推。(不過這里所需要猜解的字段名不需要是我們想要查找的字段名,只要是admin表中的字段名均可),原因請繼續往后閱讀:
  • 微調payload:

    • ?id=1513 union select top 1 1,2,3,4,5,6,7,8,9,10,b.id, * from (admin a inner join admin b on a.id=b.id)
    • 根據頁面返回的數據,我們可以看到,在第13號顯示位我們成功的爆出了admin字段的第一個值:admin
    • 原因:
      • 我們先觀察sql語句,發現union關鍵字后面的select查詢的填充字段多了代碼“b.id”,意思是在此輸出b表(admin表的別名之一)的id字段值,由於此處已經顯式的指出id字段值的輸出位置,那么后面的 “ * ” 就會自動的識別,就只輸出admin自聯表剩下的字段值了,從而使得剩余數據均向后移動了一個字段,讓原本在13號字段的admin字段向后移動了1位,到了13號顯示位上了。
      • 但請注意:此處的id字段名是我們已經猜解出的
      • 這也就回答了上述所說的:“向后移動的字段數仍然取決於:我們能夠猜解出admin表中多少個字段名,不過這里所需要猜解的字段名不需要必須是我們想要查找的字段名,只要是admin表中的字段名均可”。因此,如果我們想讓admin數據向后移動2個字段值,那么我們就需要知道除了id字段名外,其他任一字段名即可,然后構造如下payload:?id=1513 union select top 1 1,2,3,4,5,6,7,8,9,10,b.id,b.字段名 * from (admin a inner join admin b on a.id=b.id)
        14_access偏移注入-微調

5. 總結與反思

  • 至此,整個測試已結束,我們成功的爆出了 賬號與密碼:admin/a48e190faf
  • 接下來我會依次提出幾個問題,然后一一進行解答:
    1. 如果我們仍然采用上述環境,那可不可以進行3級偏移和四級偏移呢?
      • 答:3級偏移可以,但是4級偏移不行,因為如果進行4級偏移的話,就會使得偏移注入基本公式:聯合查詢補充字段數=當前字段數量-目標表的字段數 x 4 ==> 22-6x4=-2<0,即:會造成union關鍵字之前的select查詢字段數的數量 < union關鍵字之后的字段數量,從而導致查詢失敗。
      • 3級偏移的payload:?id=1513 union select top 1 1,2,3,4, * from((admin as a inner join admin as b on a.id=b.id) inner join admin as c on a.id=c.id)
    2. access偏移注入是否是真的隨機?
      • 通過上述原理的講解,這個問題也就不攻自破了,顯然access注入並不是真正的隨機,並不是完全不受我們控制的,在我們獲取足夠信息的情況下(“目標表”的字段數量,當前字段數量,已知的“目標表字段名"的數量),我們可以在一定范圍內完全控制顯示位處的數據顯示,而之所以說是一定范圍內,只是因為 “顯示位的位置” 和 “我們可以猜解到的目標表字段名的數量” 這兩個因素不是我們可以控制的。
    3. 是否可以只說:“當前表”的字段數越多成功率越大,或“目標表”的字段數越少成功率越大?
      • 顯然我們不能這樣簡單的得出結論,偏移注入是否能夠成功,取決於:“顯示位位置” 和 “目標字段能夠移動到的位置” 是否可以重合,如果可以重合的話,即使“當前表”字段數小一點,“目標表”字段數多一點也是無妨的(但萬萬不可“當前表”的字段數量 < “目標表”的字段數量)
    4. 是什么決定着“目標表”的數據一次性前移的字段數?是什么決定着“目標表”的數據可以后移的字段數?
      • 前者是由 “目標表的字段數量” 所決定的:目標表中的數據 向前移動的字段數 只能是 目標表中的字段數的整數倍(這是由表自連接的特性所決定的)。
      • 后者是由 “我們可以猜解得到的目標表的字段名數量” 所決定。若猜解出1個字段名,那么我們就可以讓數據向后移動1個字段數,若猜解出2個字段名,那么我們就可以讓數據向后移動2個字段數,以此類推。(不過這里所需要猜解的字段名不需要必須是我們想要查找的字段名,只要是admin表中的字段名均可)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM